多态性和依赖注入,如何在不实例化的情况下选择子类



对于 DI,我一直使用的方法是构造函数注入。 同样使用 DI,依赖类被注入到调用类中,无需实例化依赖类。

考虑下面的代码,我需要确定使用哪个具体类。 如何在不手动实例化类的情况下选择合适的具体类(因为使用 DI,注入器会为您完成(? 代码都是手写的,请原谅任何错别字:)

public interface IMyInterface
{
void DoSomething();
}
public class SuperClass : IMyInterface
{
private DependencyClass _dependency;
public SuperClass(DependencyClass dependency)
{
_dependency = dependency;
}
public abstract void DoSomething();
}
public class ChildClassCommon : SuperClass
{
private DependencyClass _dependency;
public ChildClassCommon(DependencyClass dependency)
{
_dependency = dependency;
}
public override void DoSomething()
{
}
}
public class ChildClassSpecial : SuperClass
{
private DependencyClass _dependency;
public ChildClassSpecial(DependencyClass dependency)
{
_dependency = dependency;
}
public override void DoSomething()
{
}
}

public class Main()
{
private IMyInterface _myClass;
public Main(IMyInterface myClass)
{
_myClass = myClass;
}
public void Selector(string recordType)
{
if(recordType == "Common")
{
// without DI, i would normally just do a new here to 
// instantiate the concrete class, but with DI, I shouldnt be
// instantiating a new instance, but how do I select which
// concrete class to use?
_myClass = new ChildClassCommon(DependencyClass dependency);
}
else if (recordType == "Special")
{
_myClass = new ChildClassSpecial(DependencyClass dependency);
}
_myClass.DoSomething();
}
}

您可以注册所有已实现的类和工厂类。之后,您可以解决工厂类。当你有工厂类时,你生成了具有特定生成规则的所需对象。

在此示例中,我使用 DI 工具Autofac

class Program
{
public class DependencyClass { }
public interface IMyInterface
{
void DoSomething();
}
public abstract class SuperClass : IMyInterface
{
protected DependencyClass _dependency;
public SuperClass(DependencyClass dependency)
{
_dependency = dependency;
}
abstract public void DoSomething();
}
public class ChildClassCommon : SuperClass
{
public ChildClassCommon(DependencyClass dependency) : base(dependency){}
public override void DoSomething(){}
}
public class ChildClassSpecial : SuperClass
{
public ChildClassSpecial(DependencyClass dependency) : base(dependency){}
public override void DoSomething(){}
}
public class MyInterfaceFactory
{
private IEnumerable<IMyInterface> _myInterfaces;
public MyInterfaceFactory(IEnumerable<IMyInterface> myInterfaces)
{
_myInterfaces = myInterfaces;
}
public IMyInterface Generate(string rule)
{
IMyInterface myObject;
if (rule == "a")
myObject = _myInterfaces.First(x => x is ChildClassCommon);
else
myObject = _myInterfaces.First(x => x is ChildClassSpecial);
return myObject;
}
}
// Injection run in this
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<DependencyClass>().AsSelf();

builder.RegisterType<MyInterfaceFactory>().AsSelf();
var assembly = Assembly.GetExecutingAssembly();
builder
.RegisterAssemblyTypes(assembly)
.AssignableTo<IMyInterface>()
.AsImplementedInterfaces();
var container = builder.Build();
var factory = container.Resolve<MyInterfaceFactory>();
IMyInterface myInterface = factory.Generate("a");
Console.WriteLine(myInterface.GetType());
Console.ReadKey();
}
}

我不确定我是否很好地理解了你,但是如果你不想实例化一个类并且你想使用它,也许可以尝试反思?您可以获取指定的类,然后调用它的方法。

如果我没看错,那么如果您当时不想实例化对象,那么typeof()可以选择引用您的具体类型。

public static Type Selector(string recordType)
{
Type concreteType;
switch (recordType)
{
case "Common":
concreteType = typeof(ChildClassCommon);
break;
case "Special":
concreteType = typeof(ChildClassSpecial);
break;
default:
concreteType = null;
break;
}
return concreteType;
}

但要理解,在某些时候,您需要实例化对象才能在应用程序中使用。因此,在上面的示例中,要实例化,您可以将反射与 DI 参数一起使用,如下所示:

var type = Selector("Common");
var myObject = (IMyInterface) Activator.CreateInstance(type, new object[] { dependency });

MSDN:

typeof()

Type

我是个白痴,我可以很容易地投掷它。 一边看电视一边回答了我自己的问题:D

if(recordType == "Common")
{
((ChildClassCommon)_myClass).DoSomething();
}
else if (recordType == "Special")
{
((ChildClassSpecial)_myClass).DoSomething();
}

相关内容

最新更新