C# 为变量声明和赋值使用动态生成的类型
在下面的问题中,可以像这样动态创建类型和实例表单:C# 为变量声明和赋值使用动态生成的类型,c#,generics,C#,Generics,在下面的问题中,可以像这样动态创建类型和实例表单: var type = typeof(AnimalContext<>).MakeGenericType(a.GetType()); var a_Context = Activator.CreateInstance(type); private int HandleInstance(Type itemType, //other args) { if (itemType == Type.type1) { t
var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
var a_Context = Activator.CreateInstance(type);
private int HandleInstance(Type itemType, //other args) {
if (itemType == Type.type1) {
topManagerInstance.manager1Instance.ImplementedMethod(//args):
}
elseif (itemType == Type.type2) {
topManagerInstance.manager2Instance.ImplementedMethod(//args):
}
...not meaningful code
{
// The enum you use for mapping
public enum Thing
{
Foo,
Bar
}
// The various implementations...
public interface ISomeInterface
{
void SomeMethod();
}
public class Foo : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Foo method!");
}
public class Bar : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Bar method!");
}
public class MyThingFactory
{
private Dictionary<Thing, ISomeInterface> _registry;
public MyThingFactory()
{
_registry = new Dictionary<Thing, ISomeInterface>
{
{Thing.Foo, new Foo()},
{Thing.Bar, new Bar()},
};
}
public void RunMethod(Thing thing)
{
if(!_registry.TryGetValue(thing, out var item))
{
throw new ArgumentOutOfRangeException(nameof(thing));
}
item.SomeMethod();
}
}
// You may want to make this static for performance reasons since you won't recreate
// the dictionary every time
var factory = new MyThingFactory();
factory.RunMethod(Thing.Foo);
factory.RunMethod(Thing.Bar);
//Output:
//Foo method!
//Bar method!
但是我不能将创建的类型(var type=typeof(AnimalContext).MakeGenericType(a.GetType());
用于声明。这可能吗
编辑:
出现需求的简短场景说明。我需要调用一个将从“topManager”调用的方法,此topManager持有实现相同基本接口的类型type1Manager
和type2Manager
的各自实例IMyInterface
方法ImplementedMethod
我想做的事情,可以用if
s解决,如下所示:
var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
var a_Context = Activator.CreateInstance(type);
private int HandleInstance(Type itemType, //other args) {
if (itemType == Type.type1) {
topManagerInstance.manager1Instance.ImplementedMethod(//args):
}
elseif (itemType == Type.type2) {
topManagerInstance.manager2Instance.ImplementedMethod(//args):
}
...not meaningful code
{
// The enum you use for mapping
public enum Thing
{
Foo,
Bar
}
// The various implementations...
public interface ISomeInterface
{
void SomeMethod();
}
public class Foo : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Foo method!");
}
public class Bar : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Bar method!");
}
public class MyThingFactory
{
private Dictionary<Thing, ISomeInterface> _registry;
public MyThingFactory()
{
_registry = new Dictionary<Thing, ISomeInterface>
{
{Thing.Foo, new Foo()},
{Thing.Bar, new Bar()},
};
}
public void RunMethod(Thing thing)
{
if(!_registry.TryGetValue(thing, out var item))
{
throw new ArgumentOutOfRangeException(nameof(thing));
}
item.SomeMethod();
}
}
// You may want to make this static for performance reasons since you won't recreate
// the dictionary every time
var factory = new MyThingFactory();
factory.RunMethod(Thing.Foo);
factory.RunMethod(Thing.Bar);
//Output:
//Foo method!
//Bar method!
但是,我想知道是否可以通过处理类型来避免使用if
s来解决这个问题,比如(用来找出问题关键的大写字母,而不是大声喊叫):
private int HandleInstance(类型itemType,//其他参数){
类型managerType=itemType==Type.type1?类型(managerType):
typeof(manager2Type);
Type[]managerTypeArray={managerType,typeof(int)};
var myDynamicallyCreatedType=typeof(IMyInterface);
//问题的关键。这就是我要问的
//将创建的变量分配给动态创建的类型以调用相应的方法
myDynamicallyCreatedType variableName=topManagerInstance.type1Manager;
//基本类型。任何要分配的type1ManagerType或type2ManagerType,如
//它们继承自同一IMyInterface,创建的类型为
//一般的
variableName.ImplementedMethod(//args):
}
看起来您只是想将枚举值映射到特定实现中的函数调用。一种方法是让一个工厂类使用字典作为映射来处理它。例如:
给定如下设置:
var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
var a_Context = Activator.CreateInstance(type);
private int HandleInstance(Type itemType, //other args) {
if (itemType == Type.type1) {
topManagerInstance.manager1Instance.ImplementedMethod(//args):
}
elseif (itemType == Type.type2) {
topManagerInstance.manager2Instance.ImplementedMethod(//args):
}
...not meaningful code
{
// The enum you use for mapping
public enum Thing
{
Foo,
Bar
}
// The various implementations...
public interface ISomeInterface
{
void SomeMethod();
}
public class Foo : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Foo method!");
}
public class Bar : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Bar method!");
}
public class MyThingFactory
{
private Dictionary<Thing, ISomeInterface> _registry;
public MyThingFactory()
{
_registry = new Dictionary<Thing, ISomeInterface>
{
{Thing.Foo, new Foo()},
{Thing.Bar, new Bar()},
};
}
public void RunMethod(Thing thing)
{
if(!_registry.TryGetValue(thing, out var item))
{
throw new ArgumentOutOfRangeException(nameof(thing));
}
item.SomeMethod();
}
}
// You may want to make this static for performance reasons since you won't recreate
// the dictionary every time
var factory = new MyThingFactory();
factory.RunMethod(Thing.Foo);
factory.RunMethod(Thing.Bar);
//Output:
//Foo method!
//Bar method!
现在你可以有一个这样的工厂:
var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
var a_Context = Activator.CreateInstance(type);
private int HandleInstance(Type itemType, //other args) {
if (itemType == Type.type1) {
topManagerInstance.manager1Instance.ImplementedMethod(//args):
}
elseif (itemType == Type.type2) {
topManagerInstance.manager2Instance.ImplementedMethod(//args):
}
...not meaningful code
{
// The enum you use for mapping
public enum Thing
{
Foo,
Bar
}
// The various implementations...
public interface ISomeInterface
{
void SomeMethod();
}
public class Foo : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Foo method!");
}
public class Bar : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Bar method!");
}
public class MyThingFactory
{
private Dictionary<Thing, ISomeInterface> _registry;
public MyThingFactory()
{
_registry = new Dictionary<Thing, ISomeInterface>
{
{Thing.Foo, new Foo()},
{Thing.Bar, new Bar()},
};
}
public void RunMethod(Thing thing)
{
if(!_registry.TryGetValue(thing, out var item))
{
throw new ArgumentOutOfRangeException(nameof(thing));
}
item.SomeMethod();
}
}
// You may want to make this static for performance reasons since you won't recreate
// the dictionary every time
var factory = new MyThingFactory();
factory.RunMethod(Thing.Foo);
factory.RunMethod(Thing.Bar);
//Output:
//Foo method!
//Bar method!
你不能,因为它没有意义…
myDynamicallyCreatedType
将在运行时而不是编译时知道。我真的不清楚你想在这里实现什么。通常当我看到有人试图像这样动态创建类型时,这是一种代码味道,但没有任何上下文,很难说。@Selvin我明白了,谢谢你的提醒我检查了名称空间,似乎不太可能,但无法基于动态创建的类型进行变量赋值?如Activator.CreateInstance(type);
,类似于Activator.Assign()
?您的a_上下文
是一个对象。您唯一的机会就是转换到所需的类型:列出a_上下文_类型=(列出)a_上下文;
。但是,您必须在编译时知道它是什么类型。您可以使用接口和逆变/协方差(取决于需要)这似乎正是我一直在寻找的。我稍后会尝试一下,并让您知道它是否符合我的需要。情况是,这涉及到另一层复杂性,因为我的界面具有泛型,Foo
和Bar
是确定类型的特定实现。更好地解释了。谢谢谢谢你的帮助!!