[英]Return instance using reflection in C#
下面給出了我嘗試返回類實例的示例代碼。
public object getConstructorclass(int i)
{
if(i==1)
{
Type type = Type.GetType("test1");
}else
{
Type type = Type.GetType("test2");
}
return Activator.CreateInstance(type);
}
var objcls = getConstructorclass(1);
objcls.callclass();//error occured
我如何在這里提到類類型,因為該類型在編譯時未知,但它將在運行時決定。在上面的示例中,我只是傳遞了一個值1(它可以是任何值,並且該類將被相應地調用),並且類test1被調用。
在這里,我會在objcls.callclass()
行上objcls.callclass()
錯誤,因為objcls
是一個沒有callclass()
方法的object
實例。
我如何重組這段代碼? 我的目的是,如果我在getConstructorclass()
方法中提到一個類,則應返回一個對象,以便在進一步的代碼中使用該對象來調用該類的成員。
如果您知道您的類將使用此方法,則應為其使用通用接口並相應地實現它。 然后,您將使用確保它可以正常工作的類。
看起來像這樣
IMyInterface objcls = getconstrorclass() as IMyInterface;
if (objcls != null)
objcls.callclass();
else
// we failed miserably and should do something about it
如果您的類沒有任何共同點,我不認為您應該使用基於int變量的通用對象返回構造函數。 像這樣處理它真的很奇怪,它可能會導致各種問題(其中一些您目前已經遇到過)。 如果類之間有些關聯,並且可以預測結果,則通用類構造函數很有意義,但是您可以創建一個“萬事俱備”的方法。不確定這種方法的正確性。
無論如何,如果您堅持(不建議這樣做,但您願意),則可以為如下類型創建一些檢查:
var createdObject = getConstructorclass(1);
if (createdObject is MyClass1)
{
var specificObject = (MyClass1)createdObject;
specificObject.callMethod1();
}
else if (createdObject is MyClass2)
{
var specificObject = (MyClass2)createdObject;
specificObject.callSomeOtherMethod();
}
...
但是它很快就會變得非常容易出錯,重構可能是一場噩夢,等等,但這是您的要求。
或者您也許可以使用pwas的解決方案,但是對我來說,對於這樣的基本任務而言,它似乎不必要地復雜。 看起來不錯,但它仍然只返回類型“ object”,因此並不能真正解決您的特定問題。
另外,要解決一個問題,我不確定您是否理解-您已經創建了實例,只需返回type對象。 這就是為什么您不能在此對象上調用任何特定方法的原因,因為首先您必須將其強制轉換為某種實際具有該方法的對象,並確保可以進行強制轉換(繼承等)。
如果interface
解決方案(請參閱其他答案)足夠,請不要看此答案。 當您不能使用通用基類/接口並且仍然需要調用成員時,可以將解決方案與is
關鍵字(以及檢查類型)一起使用。 您可以使用流利的API,而不是為每種情況編寫許多ifs:
object obj = this.getConstructorclass();
obj.StronglyInvoke()
.When<int>(value => Console.WriteLine("Got {0} as int", value))
.When<string>(value => Console.WriteLine("Got {0} as string", value))
.OnFail(() => Debug.Write("No handle."))
.Invoke();
解:
public class GenericCaller
{
private IList<GenericInvoker> invokers = new List<GenericInvoker>();
private readonly object target;
private Action failAction;
public GenericCaller(object target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
this.target = target;
}
public GenericCaller OnFail(Action fail)
{
this.failAction = fail;
return this;
}
public GenericCaller When<T>(Action<T> then)
{
if (then == null)
{
throw new ArgumentNullException("then");
}
var invoker = new GenericInvoker<T>(this.target, then);
this.invokers.Add(invoker);
return this;
}
public void Invoke()
{
if (this.invokers.Any(invoker => invoker.Invoke()))
{
return;
}
if (this.failAction == null)
{
throw new InvalidOperationException("Handler not found");
}
this.failAction();
}
public abstract class GenericInvoker
{
protected readonly object target;
protected GenericInvoker(object target)
{
this.target = target;
}
public abstract bool Invoke();
}
public class GenericInvoker<T> : GenericInvoker
{
private readonly Action<T> then;
public GenericInvoker(object target, Action<T> then)
: base(target)
{
this.then = then;
}
public override bool Invoke()
{
if (this.target.GetType() == typeof(T))
{
this.then((T)this.target);
return true;
}
return false;
}
}
}
public static class Extensions
{
public static GenericCaller StronglyInvoke(this object o)
{
return new GenericCaller(o);
}
}
記住 -使用通用接口(如其他答案所說)會更優雅-我是唯一的替代方法。
聲明變量為動態
dynamic objcls = getconstrorclass();
使用此方法,無論getconstrorclass
方法返回什么,都將在運行時確定。 您可以訪問該類型的任何成員,並且在編譯時不會出現任何錯誤。 但是,如果嘗試訪問一個不存在的成員,則在運行時會收到RuntimeBinderException
。
我建議使用interface
並將可以通過這種方式實例化的類限制為僅實現接口的類。
public interface IMyInterface
{
void callclass();
}
public <T> getConstructorClass()
{
T instance;
Type type = Type.GetType("test1");
// instance will be null if the object cannot be cast to type T.
instance = Activator.CreateInstance(type) as T;
return T;
}
IMyInterface objcls = getConstructorClass<IMyInterface>();
if(null != objcls)
{
objcls.callclass();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.