Activator.CreateInstance:类的动态实例化
我正在设计一个松耦合的结构。我想通过由字符串表示的代码从不同的程序集/命名空间调用类。我的设计是,每个客户端的业务规则都位于不同的程序集上,并且彼此不依赖(一个客户端与一个 DLL 的比例),这样当我对 1 个客户端的业务规则进行更新时,不会影响其他客户端。我现在的注意力是使用 Factory Design 和使用 Activator.CreateInstance() 方法。
这是项目设置(2+n DLL)
namespace Foundation; // where the interfaces/abstract resides
namespace Factory; // has dependency on Foundation assembly
namespace Client1; // client1's DLL, no dependency
namespace Client2; // client2's DLL, no dependency
The UI // only referenced to the Foundation and Factory not the Clients
实际代码
namespace Foundation
{
public interface IBusinessRules
{
string GetBusinessRule();
}
}
namespace Client1 //DLL for client 1
{
public class BusinessRules : Foundation.IBusinessRules
{
public string GetBusinessRule()
{
return "Client1 Business Rule";
}
}
}
namespace Client2 //DLL for client 2
{
public class BusinessRules : Foundation.IBusinessRules
{
public string GetBusinessRule()
{
return "Client2 Business Rule";
}
}
}
namespace Factory
{
public static class Invoker<T> where T: Foundation.IBusinessRules
{
public static T FetchInstance(string clientCode)
{
return (T)Activator.CreateInstance(Type.GetType(clientCode));
}
}
}
//sample implementation that generates unhandled Exception
using Factory;
using Foundation;
static void Main(string[] args)
{
//the parameter is maintained in the database
IBusinessRules objClient1 = Invoker<IBusinessRules>.FetchInstance("Client1");
//should call Client1.BusinessRules method
Console.WriteLine(objClient.GetBusinessRule());
Console.Read();
objClient = Invoker<IBusinessRules>.FetchInstance("Client2");
//should call Client2.BusinessRules method
Console.WriteLine(objClient.GetBusinessRule());
Console.Read();
}
知道为什么我的示例不起作用吗?有什么改进设计的建议吗? 提前致谢。
如何使用
表达式.Lambda
有人吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您使用 FetchInstance("Client.BusinessRules") 您的代码可以工作,前提是所有内容都在同一个程序集中。如果不是(根据您的设计),您需要提供 AssemblyQualifiedName。
不过我会做不同的设计。保留仅使用“Client1”作为参数的调用,但更改工厂的实现。动态加载给定客户端的程序集(使用 Assembly.Load() 或 Assembly.LoadFrom()),然后使用 clientAssembly.CreateInstance() 实例化您的类型。
编辑:原始代码示例:
如果您不知道 client-dll 中的类名,则必须搜索适用的类型,例如使用 clientAssembly.GetTypes()。
If you use FetchInstance("Client.BusinessRules") your code works, IF everything is in the same assembly. If it's not (as per your design) you need to give an AssemblyQualifiedName.
I would do the design differently though. Keep your call with just "Client1" as Parameter but change the implementation of the Factory. Dynamically load the assembly for the given client (with Assembly.Load() or Assembly.LoadFrom()), then use clientAssembly.CreateInstance() to istantiate your type.
Edit: Crude code sample:
If you dont't know the class name in the client-dll, you have to search for an applicable Type, for example with clientAssembly.GetTypes().
感谢你们的帮助,我终于明白了!我只是修改了工厂
,但我想知道它的效率(性能影响),因为它使用反射..
Thanks to your help guys i finally Got it! I just modify the Factory
But I wonder about its effeciency (performance hit) because it uses Reflection..
您需要使用班级的全名。
例如:
You need to use the full name of the class.
for example:
如果您从外部程序集加载类型,我建议使用
Activator.CreateInstanceFrom
。If you are loading the type from an external assembly, I would recommend using
Activator.CreateInstanceFrom
.如果您希望能够在部署后将业务规则添加为 dll 并在运行时创建它们,我建议您在应用程序下有一个业务规则文件夹,加载该应用程序中的所有 dll,搜索每个 dll 中实现 IBusinessRules 的所有类型使用反射。鉴于您现在已经掌握了这些类型,因此根据名称创建一个类型将很容易,并且您的项目将会扩展。
或者,或者将类的程序集限定名称传递给您的方法。
If you want to be able to add business rules as dlls after deployment and create them at runtime, I suggest you have a business rules folder under you app, load all dlls in that app, search for all types that implement of IBusinessRules in each dll using reflection. Given that you now have handles on the types, creating one based on name would be easy and your project would scale out.
Either that, or pass the assembly qualified name of the classes to your methods.