作为一个简单的例子,我有一个xml文件,其中包含实际执行工作的类名称列表,并且所有类都使用方法Process()实现接口IDoWork。
我循环遍历xml文件中的项目。 如何从字符串名称实际动态地将类分配给接口? e.g。
var IDoWork = new "DoWorkType1"();
IDoWork.Process();
<work>
<item id="DoWorkType1">
</item>
<item id="DoWorkType2">
</item>
</work>
我想实现一个插件类型的体系结构,除了插件不是程序级别只是程序中的类级别。
答案 0 :(得分:3)
Type t = Type.GetType("DoWorkType1");
IDoWork idw = (IDoWork)Activator.CreateInstance(t);
idw.Process();
答案 1 :(得分:1)
基本上,您有几种选择:
- 将xml反序列化为IDowork类的集合。并在每个上执行Process
方法。
- 使用Activator.CreateInstance
手动创建对象。
- 使用一些 IoC 框架。然后,您将在应用程序启动时注册所有插件,并在IoC将构建的实例上执行您的操作。这样的事情。
//On Application Start
Container.Register("DoWorkType1", typeof(DoWorkType1));
Container.Register("DoWorkType2", typeof(DoWorkType2));
//Execute your actions
var instance = Container.Resolve<IDowork>("DoWorkType2");
instance.DoWork()
如果是IoC,我建议您使用AutoFac,StructureMap或Castle。
答案 2 :(得分:1)
如果IDoWork与DoWorkType1和DoWorkType2在同一个程序集中,您可以这样做:
Type t = typeof(IDoWork).GetAssembly().GetType("DoWorkType1");
IDoWork w = (IDoWork)Activator.CreateInstance(t);
w.Process();
感谢大家的纠正!
答案 3 :(得分:1)
如果我理解你的问题,你应该用IoC容器(如StructureMap)注册你的各种类,并使用它来在运行时动态检索特定接口类型的对象。
答案 4 :(得分:1)
是否有特定原因您不想使用number dependency injection containers中的任何一个?他们的核心是他们真正做的事情,根据一些配置/引导为一个给定的接口注入一个实现。
答案 5 :(得分:0)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Interfaces;
using Classes;
namespace Interfaces
{
public interface IDoWork
{
string Name { get; set; }
string Process();
}
}
namespace Classes
{
public class FactoryClass
{
private static readonly IDictionary<string, Type> ClassMembers
= new Dictionary<string, Type>();
public static T Create<T>(string s) where T : class
{
// if we have 'cached' the type, then use it
if (ClassMembers.ContainsKey(s))
{
return (T)Activator.CreateInstance(ClassMembers[s]);
}
// determine the concrete type
var concreteClass = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => typeof(T).IsAssignableFrom(t)
&& t.FullName.ToLower().Contains(s.ToLower()))
.FirstOrDefault();
// if we have a match - give it a ping...
if (concreteClass != null)
{
var newUnit = (T) Activator.CreateInstance(concreteClass);
ClassMembers.Add(s, concreteClass);
return (T) newUnit;
}
// for the sake of the example - return null for now
return null;
}
}
public class DoWorkType1 : IDoWork
{
public string Name { get; set; }
public bool isNew = true;
public string Process()
{
isNew = false;
return "It's me - Mr DoWorkType1";
}
}
public class DoWorkType2 : IDoWork
{
public string Name { get; set; }
public string Process()
{
return "My turn - Ms DoWorkType2";
}
}
}
class Program
{
public static void Main(string[] args)
{
var newWork = FactoryClass.Create<IDoWork>("DoWorkType1");
Console.WriteLine(newWork.Process());
newWork = FactoryClass.Create<IDoWork>("DoWorkType2");
Console.WriteLine(newWork.Process());
// repeat with DoWorkType1 just to show it coming from dictionary
newWork = FactoryClass.Create<IDoWork>("DoWorkType1");
Console.WriteLine(newWork.Process());
Console.Read();
}
}
我在一个应用程序中使用类似的方法,该应用程序从数据库字段获取类名,并使用工厂类以与上面类似的方式创建对象。这个简单的例子当然没有检查魔术字符串拼写错误,所以这是一个需要注意的附加内容。