usuario starter programa podido modo interfaz instalador instalacion iniciar hdtv error defender compatible 0x80004002 c# generics interface

c# - starter - modo de interfaz de usuario del instalador no compatible



En C#¿cómo puedo verificar si T es de tipo IInterface y convertirlo en eso si mi objeto es compatible con esa interfaz? (8)

if (typeof(IMyInterface).IsAssignableFrom(typeof(T))

Esto verifica si una variable de tipo IMyInterface se puede asignar desde una instancia de tipo T

En C #, tengo una función que pasa en T usando generics y quiero ejecutar una comprobación para ver si T es un object que implementa una interface y, de ser así, llamar a uno de los methods en esa interface .

No quiero que T restricciones T sean solo de ese tipo. ¿Es posible hacer esto?

Por ejemplo:

public class MyModel<T> : IModel<T> where T : MyObjectBase { public IQueryable<T> GetRecords() { var entities = Repository.Query<T>(); if (typeof(IFilterable).IsAssignableFrom(typeof(T))) { //Filterme is a method that takes in IEnumerable<IFilterable> entities = FilterMe(entities)); } return entities; } public IEnumerable<TResult> FilterMe<TResult>(IEnumerable<TResult> linked) where TResult : IFilterable { var dict = GetDict(); return linked.Where(r => dict.ContainsKey(r.Id)); } }

El error que estoy recibiendo es:

Error 21 El tipo ''TResult'' no se puede utilizar como parámetro de tipo ''TResult'' en el tipo genérico o método ''FilterMe (System.Collections.Generic.IEnumerable)''. No hay conversión de referencia implícita de ''TResult'' a ''IFilterable''.


Si tiene un parámetro de tipo genérico que puede o no implementar IFoo , es posible IFoo a una ubicación de almacenamiento de tipo IFoo ; si lo hace, puede pasarlo a cualquier método que espere un IFoo , así como a cualquier método que espere un parámetro genérico restringido a IFoo , pero perderá toda la información de tipo genérico si lo hace; el parámetro se aprobará como tipo IFoo . Entre otras cosas, esto significará que si su objeto original era una estructura, se enmarcará.

Si desea probar si un tipo de parámetro genérico implementa IFoo y llama a un método que toma IFoo genérico-restringido si lo hace, mientras mantiene el tipo genérico original (esto podría ser útil si el tipo es una estructura, y podría ser necesario si el tipo se pasa a un método genérico que tiene restricciones IFoo e IBar y las cosas que uno podría querer aprobar no comparten un solo supertipo común), será necesario usar Reflection.

Por ejemplo, supongamos que uno quiere tener un método Zap que toma un parámetro ref genérico, llama a Dispose si implementa IDisposable y lo borra. Si el parámetro es un tipo de clase IDisposable , se debe realizar una prueba nula como una operación atómica con la eliminación del parámetro.

public static class MaybeDisposer { static class ClassDisposer<T> where T : class,IDisposable { public static void Zap(ref T it) { T old_it = System.Threading.Interlocked.Exchange(ref it, null); if (old_it != null) { Console.WriteLine("Disposing class {0}", typeof(T)); old_it.Dispose(); } else Console.WriteLine("Class ref {0} already null", typeof(T)); } } static class StructDisposer<T> where T : struct,IDisposable { public static void Zap(ref T it) { Console.WriteLine("Disposing struct {0}", typeof(T)); it.Dispose(); it = default(T); } } static class nonDisposer<T> { public static void Zap(ref T it) { Console.WriteLine("Type {0} is not disposable", typeof(T)); it = default(T); } } class findDisposer<T> { public static ActByRef<T> Zap = InitZap; public static void InitZap(ref T it) { Type[] types = {typeof(T)}; Type t; if (!(typeof(IDisposable).IsAssignableFrom(typeof(T)))) t = typeof(MaybeDisposer.nonDisposer<>).MakeGenericType(types); else if (typeof(T).IsValueType) t = typeof(MaybeDisposer.StructDisposer<>).MakeGenericType(types); else t = typeof(MaybeDisposer.ClassDisposer<>).MakeGenericType(types); Console.WriteLine("Assigning disposer {0}", t); Zap = (ActByRef<T>)Delegate.CreateDelegate(typeof(ActByRef<T>), t, "Zap"); Zap(ref it); } } public static void Zap<T>(ref T it) { findDisposer<T>.Zap(ref it); } }

La primera vez que se invoca el código con cualquier tipo T , determinará qué tipo de clase estática genérica se puede producir para ese parámetro y usar Reflection para crear un delegado que llame a un método estático de esa clase genérica. Las llamadas posteriores con el mismo tipo T utilizarán el delegado almacenado en caché. Aunque Reflection puede ser un poco lento, solo tendrá que usarse una vez para cualquier tipo T Todas las llamadas posteriores a MaybeDisposer.Zap<T>(ref T it) con el mismo tipo T enviarán directamente a través del delegado y, por lo tanto, se ejecutarán rápidamente.

Tenga en cuenta que las llamadas a MakeGenericType arrojarán excepciones si reciben parámetros de tipo genérico que no cumplen con las restricciones de las clases genéricas abiertas (por ejemplo, si T fue una clase o no implementó IDisposable , un intento de hacer que el tipo genérico StructDisposer<T> lanzaría una excepción); tales pruebas ocurren en tiempo de ejecución y no son validadas por el compilador, por lo que puede usar la verificación en tiempo de ejecución para ver si los tipos cumplen con las restricciones apropiadas. Tenga en cuenta que el código no prueba si implementa IDisposable , sino que prueba si T hace. Esto es muy importante. De lo contrario, si se MaybeDispose con un parámetro de tipo Object que contenía una referencia a Stream , determinaría que implementó IDisposable y, por lo tanto, intentará crear un ClassDisposer<Object> , estrellándose porque Object no implementa IDisposable .


¿Es el OfType(...) ( enlace ) lo que estás buscando?

public class MyModel<T> : IModel<T> where T : MyObjectBase { public IQueryable<T> GetRecords() { var entities = Repository.Query<T>(); if (typeof(IFilterable).IsAssignableFrom(typeof(T))) { //Filterme is a method that takes in IEnumerable<IFilterable> entities = FilterMe(entities)); } return entities; } public IEnumerable<TResult> FilterMe<TResult>(IEnumerable<TResult> linked) where TResult : IFilterable { var dict = GetDict(); return linked.OfType<TResult>().Where(r => dict.ContainsKey(r.Id)); } }


En mi respuesta, asumo que el método FilterMe se usa internamente y no debería ser visible fuera de su modelo y podría marcarse como private . Si mi suposición es incorrecta, podría crear una sobrecarga privada de FilterMe .

En mi respuesta, simplemente <TResult> genérico. Supongo que este FilterMe siempre trata sobre las entidades de tipo T (ya que está en la misma clase Model). Esto resuelve el problema de la conversión entre T y TResult . TResult no tiene que marcarse como IFilterable ya que no se IFilterable ninguno de los miembros de IFilterable . Y dado que el código ya verifica si T es IFilterable ¿ IFilterable qué verificar nuevamente (especialmente cuando FilterMe sería privado)?

public IQueryable<T> GetRecords() { var entities = Repository.Query<T>(); if (typeof(IFilterable).IsAssignableFrom(typeof(T))) { //Filterme is a method that takes in IEnumerable<IFilterable> entities = FilterMe(entities).AsQueryable(); } return entities; } public IEnumerable<T> FilterMe(IEnumerable<T> linked) { var dict = GetDict(); return linked.Where(r => dict.ContainsKey(r.Id)); }

Si creara un segundo FilterMe , reemplace los IEumerable<T> con Queryable<T> , para que no tenga que convertir sus entidades con AsQueryable() .


La forma más simple que se me ocurre es algo así como:

public IEnumerable<T> GetRecords() { IQueryable<T> entities = new List<T>().AsQueryable(); if (typeof(IFilterable).IsAssignableFrom(typeof(T))) { entities = FilterMe<IFilterable, T>(entities.OfType<IFilterable>()).AsQueryable(); } return entities; } public IEnumerable<TResult> FilterMe<TSource, TResult>(IEnumerable<TSource> linked) where TSource : IFilterable { return linked.Where(r => true).OfType<TResult>(); }

El punto aquí es la necesidad de tener tipos para pasar y salir del método. Tuve que cambiar los tipos localmente para que funcione.

OfType silenciosa los elementos que no son realmente de un tipo dado, por lo que asume que es una colección del mismo tipo en cualquier llamada.

Debido a que está reasignando desde FilterMe , aún necesita la verificación asignable de la interfaz.


La pieza faltante es Cast<>() :

if(typeof(IFilterable).IsAssignableFrom(typeof(T))) { entities = FilterMe(entities.Cast<IFilterable>()).AsQueryable().Cast<T>(); }

Tenga en cuenta el uso de Cast<>() para convertir la lista de entidades al subtipo correcto. Este elenco fallará a menos que T implemente IFilterable , pero como ya lo hemos comprobado, sabemos que sí lo hará.


public IEnumerable<TResult> FilterMe<TResult>(IEnumerable<TResult> linked) where TResult : IFilterable { var dict = GetDict(); return linked.Where(r => dict.ContainsKey(r.Id)); }

Intente reemplazar FilterMe con esta versión:

public IEnumerable<T> FilterMe(IEnumerable<IFilterable> linked) { var dict = GetDict(); return linked.Where(r => dict.ContainsKey(r.Id)).Cast<T>(); }

Entonces, si fueras tu llamada, cambia tu código a este:

if (typeof(IFilterable).IsAssignableFrom(typeof(T))) { //Filterme is a method that takes in IEnumerable<IFilterable> var filterable = entities.Cast<IFilterable>(); entities = FilterMe(entities).AsQueryable(); }


No es necesario que el método FilterMe un método genérico para lograr el mismo resultado.

public class MyModel<T> : IModel<T> where T : MyObjectBase { public IQueryable<T> GetRecords() { var entities = Repository.Query<T>(); if (typeof(IFilterable).IsAssignableFrom(typeof(T))) { //Filterme is a method that takes in IEnumerable<IFilterable> entities = FilterMe(entities.Cast<IFilterable>()); } return entities; } public IEnumerable<T> FilterMe(IEnumerable<IFilterable> linked) { var dict = GetDict(); return linked .Where(r => dict.ContainsKey(r.Id)) .Cast<T>(); } }