我可以在编译时声明Type 的变量而不指定T吗?

如何动态加载“MyContent”类? 我有1个interface ,1个抽象genericsclass和1个类。 检查我的代码:

 public interface IMyObjectInterface{ } public abstract MyAbstractObject : IMyObjectInterface{ } public class MyObject : MyAbstractObject{ } public interface IMyContentInterface where T : MyAbstractObject { void MyMethod(); } public abstract MyAbstractContent, IMyContentInterface where T : MyAbstractObject { public abstract void MyMethod(); } public public class MyContent : MyAbstractContent { public override void MyMethod() { //do something } } 

我正在尝试,但显然它不起作用:

 IMyObjectInterface obj = (IMyObjectInterface)Assembly.Load("MyAssembly").CreateInstance("MyObject"); IMyContentInterface content = (IMyContentInterface)Assembly.Load("MyAssembly").CreateInstance("MyContent"); content.MyMethod(); //assembly and type names are correct 

如果我将IMyContentInterface更改为IMyContentInterface ,则有效:

 IMyContentInterface content = (IMyContentInterface)Assembly.Load("MyAssembly").CreateInstance("MyContent"); content.MyMethod(); //assembly and type names are correct 

问题是,当定义IMyContentInterface时,我不会在第二行中成为我的对象。 请问有人知道如何在.NET Framework 4.0中执行此操作吗?

< >的项必须是类型而不是对象。

我的车是汽车的一个对象所以

 Car myCar=new Car(); 

我想要一个列表来保存我的汽车(Car类型的对象)。

 List myCars = new List(); 

然后我们将Car类型的对象添加到我的列表中。

  myCars.Add(myCar); myCars.Add(anotherCar); 

如何动态加载“MyContent”类?

加载它并不难 – 您已经知道如何做到这一点,但C#generics在编译时是强类型,检查和保证。 考虑以下代码:

 List list = new List(); list.Add(new TcpSocket()); // This line won't compile 

如果你被允许声明这样的generics,C#编译器不能告诉你这是非法的:

 Type type = GetTypeFromReflectedAssembly(); List list = new List(); // This *might* work - who knows? list.Add(new TcpSocket()); 

如果您的最终目标是调用MyContent.MyMethod()并且与generics类型参数没有任何关系,请考虑声明一个非generics接口,您可以在inheritance层次结构中的某处实现并声明您的实例变量使用它:

 IMyContentInterface content = (IMyContentInterface)Assembly.Load("MyAssembly").CreateInstance("MyContent"); content.MyMethod(); 

我不得不读了几遍,但我弄清楚你在问什么。 :)这个问题是另一个问题的具体实例:

  • 将实例化的System.Type作为generics类的类型参数传递

也就是说,这是一个如何将它用于测试用例的示例。 显然你可以改变它。 另外,请不要错过本回答末尾的最后一点。

汇编MyCompany.MyProduct.MyComponent:

在此程序集中定义接口:

 namespace MyCompany.MyProduct.MyComponent { public interface IMyObjectInterface { void MyObjectMethod(); } /* It's important to include this non-generic interface as a base for * IMyContentInterface because you will be able to reference this * in the assembly where you load components dynamically. */ public interface IMyContentInterface { Type ObjectType { get; } void MyContentMethod(); } public interface IMyContentInterface : IMyContentInterface where T : IMyObjectInterface { } } 

汇编MyCompany.MyProduct.MyComponent.Implementation:

在此程序集中实现将动态加载的接口。

 namespace MyCompany.MyProduct.MyComponent { public abstract class MyAbstractObject : IMyObjectInterface { public abstract void MyObjectMethod(); } public class MyObject : MyAbstractObject { public override void MyObjectMethod() { } } public abstract class MyAbstractContent : IMyContentInterface where T : MyAbstractObject { public Type ObjectType { get { return typeof(T); } } public abstract void MyContentMethod(); } public class MyContent : MyAbstractContent { public override void MyContentMethod() { } } } 

汇编MyCompany.MyProduct

您的程序由此程序集组成 ,这是我从Managed Extensibility Framework中提取的术语。 此程序集引用MyCompany.MyProduct.MyComponent而不是MyCompany.MyProduct.MyComponent.Implementation ,前提是接口比产品开发期间的实现更可能保持兼容 。 这种设计是为了有利于凝聚力而不是耦合 (一对经常被误解的词),但实际的实施往往在实现这一目标的成功方面有很大差异。

 namespace MyCompany.MyProduct { using MyCompany.MyProduct.MyComponent; using System.Reflection; using System.Security.Policy; public class ComponentHost { public void LoadComponents() { Assembly implementation = LoadImplementationAssembly(); /* The implementation assembly path might be loaded from an XML or * similar configuration file */ Type objectType = implementation.GetType("MyCompany.MyProduct.MyComponent.MyObject"); Type contentType = implementation.GetType("MyCompany.MyProduct.MyComponent.MyContent"); /* THIS assembly only works with IMyContentInterface (not generic), * but inside the implementation assembly, you can use the generic * type since you can reference generic type parameter in the source. */ IMyContentInterface content = (IMyContentInterface)Activator.CreateInstance(contentType); } private Assembly LoadImplementationAssembly() { /* The implementation assembly path might be loaded from an XML or * similar configuration file */ string assemblyPath = "MyCompany.MyProduct.MyComponent.Implementation.dll"; return Assembly.LoadFile(assemblyPath); } } } 

最后的说明:

Managed Extensibility Framework是作为您正在处理的问题的通用解决方案而构建的。 经过一段时间的努力,我充满信心地说它具有以下不错的属性:

  • 相对较短的学习曲线。
  • 结果非常干净的代码。
  • 运行时成本低(组件很小,性能非常好)。

如果它符合以下一项或多项的任何组合,我会很容易地推荐它作为在新应用程序上工作的人的严肃可行选项:

  • 应用程序分为几个组件(几乎任何非平凡的应用程序都是如此)。
  • 应用程序需要在未来具有灵活性或可扩展性(因为任何长期项目都是如此)。
  • 应用程序需要从未知程序集动态加载实现。

这是一种动态加载接口的方法。 这假设你有一些方法来获取你试图加载它的程序集和一个字符串作为类型的名称。

在我的例子中,我使用了一个Xml文件。 您可以使用任何方法,我不会显示这些方法,因为它可以根据您的实现进行更改。

 ISomeInterface myInterface = this.GetComponent("SomeImplementation"); public T GetComponent(string componentName) { // A method to dymanicly load a .dll, not shown in this example Assembly assembly = this.GetComponentAssembly(componentName); // A method to get a string assembly type, in this case from another source string assemblyType = this.GetAssemblyType(componentName); T component = (T)assembly.CreateInstance(assemblyType); return component; }