por lo que necesita una cosa que pueden crear instancias de un tipo desconocido que implementa una interfaz. Básicamente tiene tres opciones: un objeto de fábrica, un objeto Type o un delegado. Aquí es lo dado:
public interface IInterface
{
void DoSomething();
}
public class Foo : IInterface
{
public void DoSomething() { /* whatever */ }
}
Uso de texto es bastante feo, pero tiene sentido en algunos escenarios:
public IInterface CreateUsingType(Type thingThatCreates)
{
ConstructorInfo constructor = thingThatCreates.GetConstructor(Type.EmptyTypes);
return (IInterface)constructor.Invoke(new object[0]);
}
public void Test()
{
IInterface thing = CreateUsingType(typeof(Foo));
}
El mayor problema con él, es que en tiempo de compilación, usted no tiene ninguna garantía de que Foo realidad tiene un constructor predeterminado. Además, la reflexión es un poco lenta si se trata de un código de rendimiento crítico.
La solución más común es el uso de una fábrica:
public interface IFactory
{
IInterface Create();
}
public class Factory<T> where T : IInterface, new()
{
public IInterface Create() { return new T(); }
}
public IInterface CreateUsingFactory(IFactory factory)
{
return factory.Create();
}
public void Test()
{
IInterface thing = CreateUsingFactory(new Factory<Foo>());
}
En lo anterior, IFactory es lo que realmente importa. Factory es solo una clase de conveniencia para las clases que do proporcionan un constructor predeterminado. Esta es la solución más simple y a menudo mejor.
El tercer momento-raro-pero-probable-a-convertido-más-común solución es el uso de un delegado:
public IInterface CreateUsingDelegate(Func<IInterface> createCallback)
{
return createCallback();
}
public void Test()
{
IInterface thing = CreateUsingDelegate(() => new Foo());
}
La ventaja aquí es que el código es corto y simple, puede trabajar con cualquier método de construcción y (con cierres) le permite transferir fácilmente los datos adicionales necesarios para construir los objetos.