在C#中我有以下对象:
public class Item
{ }
public class Task<T>
{ }
public class TaskA<T> : Task<T>
{ }
public class TaskB<T> : Task<T>
{ }
Run Code Online (Sandbox Code Playgroud)
我想使用C#reflection(Activator.CreateInstance)动态创建TaskA或TaskB .但是我不知道手头的类型,所以我需要动态创建基于字符串的TaskA,如"namespace.TaskA"或"namespace.TaskAB".
昨天我问了一个关于使用反射或策略模式动态调用方法的问题.
但是,从那时起,我决定将方法更改为实现公共接口的各个类.原因是,每个类虽然具有一些相似之处,但也执行该类所特有的某些方法.
我一直在使用这样的策略:
switch (method)
{
case "Pivot":
return new Pivot(originalData);
case "GroupBy":
return new GroupBy(originalData);
case "Standard deviation":
return new StandardDeviation(originalData);
case "% phospho PRAS Protein":
return new PhosphoPRASPercentage(originalData);
case "AveragePPPperTreatment":
return new AveragePPPperTreatment(originalData);
case "AvgPPPNControl":
return new AvgPPPNControl(originalData);
case "PercentageInhibition":
return new PercentageInhibition(originalData);
default:
throw new Exception("ERROR: Method " + method + " does not exist.");
}
Run Code Online (Sandbox Code Playgroud)
但是,随着潜在类数量的增加,我将需要不断添加新类,从而打破关闭修改规则.
相反,我使用了一个解决方案:
var test = Activator.CreateInstance(null, "MBDDXDataViews."+ _class);
ICalculation instance = (ICalculation)test.Unwrap();
return instance;
Run Code Online (Sandbox Code Playgroud)
实际上,_class参数是在运行时传入的类的名称.这是一种常见的方法,这会有任何性能问题吗?
我很反思,所以欢迎你提出建议.
我有一个泛型类型Store<T>,用于Activator创建这种类型的实例.现在,在使用Activator之后,我可以将结果对象的类型转换object回实例化类型吗?我知道我用来实例化泛型的类型.请参阅以下代码:
class Store<T> where T : IStorable
{}
class Beer : IStorable
{}
class BeerStore : Store<Beer>
{}
Type storeType = someObjectThatImplementsIStorable.GetType();
Type classType = typeof(Store<>);
Type[] typeParams = new Type[] { storeType };
Type constructedType = classType.MakeGenericType(typeParams);
object x = Activator.CreateInstance(constructedType, new object[] { someParameter });
Run Code Online (Sandbox Code Playgroud)
我想做的是这样的事情:
var store = (Store<typeof(objectThatImplementsIStorable)>)x;
Run Code Online (Sandbox Code Playgroud)
但由于显而易见的原因,这不起作用.作为替代方案,我试过:
var store = (Store<IStorable>)x;
Run Code Online (Sandbox Code Playgroud)
这可能在我看来有效,但给出了一个InvalidCastException.
如何再次访问Store<T>对象中我知道的方法x?
我正在努力提高应用程序的性能.我们有很多Activator.CreateInstance调用引起了一些悲伤.
我们基于一个接口(ITabDocument)实例化了很多类,在浏览后我想到了使用这段代码:
代码并不比使用我们拥有的Activator.CreateInstance代码更好(实际上稍慢).
public static Func<T> CreateInstance<T>(Type objType) where T : class, new()
{
var dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + objType.Name, objType, null, objType);
ILGenerator ilGen = dynMethod.GetILGenerator();
ilGen.Emit(OpCodes.Newobj, objType.GetConstructor(Type.EmptyTypes));
ilGen.Emit(OpCodes.Ret);
return (Func<T>)dynMethod.CreateDelegate(typeof(Func<T>));
}
Run Code Online (Sandbox Code Playgroud)
我想知道为什么会这样,我所做的只是:
ITabDocument document = CreateInstance<ITabDocument>(Type.GetType("[Company].Something"));
Run Code Online (Sandbox Code Playgroud)
是否有更好的方法来创建有助于上述内容的对象?当你不确定具体的类型时,它有点难.
System.Activator.CreateInstance(T)方法是否有性能问题(因为我怀疑它使用反射)大到足以阻止我们随便使用它?
在我的反射代码中,我遇到了我的通用代码部分的问题.特别是当我使用一个字符串.
var oVal = (object)"Test";
var oType = oVal.GetType();
var sz = Activator.CreateInstance(oType, oVal);
Run Code Online (Sandbox Code Playgroud)
例外
An unhandled exception of type 'System.MissingMethodException' occurred in mscorlib.dll
Additional information: Constructor on type 'System.String' not found.
Run Code Online (Sandbox Code Playgroud)
我试过这个用于测试目的,它也发生在这个单一的衬里
var sz = Activator.CreateInstance("".GetType(), "Test");
Run Code Online (Sandbox Code Playgroud)
我最初写的
var sz = Activator.CreateInstance("".GetType());
Run Code Online (Sandbox Code Playgroud)
但我得到这个错误
Additional information: No parameterless constructor defined for this object.
Run Code Online (Sandbox Code Playgroud)
如何使用反射创建字符串?
我有一个类(TabControlH60),它继承自基类(UserControl)并实现一个接口(IFrameworkClient).我使用.NET Activator类实例化对象.使用返回的实例,我可以转换为UserControl基类,但不能转换为接口.我得到的例外是在代码snipet下面.如何转换为界面?
object obj = Activator.CreateInstance(objType);
Type[] interfaces = obj.GetType().GetInterfaces(); // contains IFrameworkClient
m_Client = (UserControl)obj; // base class cast works
IFrameworkClient fc = (IFrameworkClient)obj; // interface cast fails
// Note: The (IFrameworkClient)obj cast works fine in the debugger Watch window.
{"Unable to cast object of type 'FPG.H60.AFF.TabControlH60' to type
'FPG.AFF.Interfaces.IFrameworkClient'."}
Run Code Online (Sandbox Code Playgroud) 我有一个具有以下构造函数的类
public DelayCompositeDesigner(DelayComposite CompositeObject)
{
InitializeComponent();
compositeObject = CompositeObject;
}
Run Code Online (Sandbox Code Playgroud)
以及没有参数的默认构造函数.
接下来我正在尝试创建一个实例,但它只能在没有参数的情况下工作:
var designer = Activator.CreateInstance(designerAttribute.Designer);
Run Code Online (Sandbox Code Playgroud)
这工作正常,但如果我想传递参数,它不会:
var designer = Activator.CreateInstance(designerAttribute.Designer, new DelayComposite(4));
Run Code Online (Sandbox Code Playgroud)
这导致MissingMethodException:
未找到构造函数类型Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesigner
这里有什么想法?
问题是我真的需要在施工期间传递一个物体.
你看我有一个设计器,它加载了从中继承的所有类型CompositeBase.然后将这些添加到列表中,用户可以从中将它们拖动到设计器.执行此操作后,将拖动的实例添加到设计器中.这些类中的每一个都定义了自定义属性:
[CompositeMetaData("Delay","Sets the delay between commands",1)]
[CompositeDesigner(typeof(DelayCompositeDesigner))]
public class DelayComposite : CompositeBase
{
}
Run Code Online (Sandbox Code Playgroud)
当用户选择设计器中的项目时,它会查看这些属性以便为该类型加载设计器.例如,在它的情况下,DelayComposite它将加载具有标签和滑块的用户控件,该标签和滑块允许用户设置DelayComposite实例的"延迟"属性.
到目前为止,如果我没有将任何参数传递给构造函数,这可以正常工作.设计者创建一个实例DelayCompositeDesigner并将其分配给WPF的content属性ContentPresenter.
但由于该设计人员需要在设计器中修改所选属性,因此DelayComposite
我必须将此实例传递给它.这就是为什么构造函数看起来像这样:
public DelayCompositeDesigner(DelayComposite CompositeObject)
{
InitializeComponent();
compositeObject = CompositeObject;
}
Run Code Online (Sandbox Code Playgroud)
欢迎提出建议
@VolkerK
您的代码的结果是这样的:
<---- foo Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid .ctor()Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid .ctor(Vialis.LightLink.Controller.Scenarios.Composites.DelayComposite)param:Vialis .LightLink.Controller.Scenarios.Composites.DelayComposite foo ---->
Leppie,你是对的,我出于某种原因在我的UI应用程序中引用了Composites程序集......这不是我在运行时加载它时应该做的事情.以下代码有效:
object …Run Code Online (Sandbox Code Playgroud) 如果我有一个类型参数约束new():
void Foo<T>() where T : new()
{
var t = new T();
}
Run Code Online (Sandbox Code Playgroud)
在new T()内部使用该Activator.CreateInstance方法(即反射)是真的吗?
我有一个例子:
Assembly asm = Assembly.Load("ClassLibrary1");
Type ob = asm.GetType("ClassLibrary1.UserControl1");
UserControl uc = (UserControl)Activator.CreateInstance(ob);
grd.Children.Add(uc);
Run Code Online (Sandbox Code Playgroud)
我正在创建一个类的实例,但是如何创建实现某个接口的类的实例?即UserControl1实现ILoad接口.
U:我可以稍后将对象转换为接口,但我不知道程序集中的哪个类型实现了接口.
activator ×10
c# ×9
reflection ×7
.net ×4
generics ×3
base-class ×1
casting ×1
interface ×1
performance ×1