在C#中返回的实例使用反射(Return instance using reflection in

2019-10-20 21:24发布

我试图返回类的实例,示例代码如下所示。

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

我怎么能在这里提到的类类型,因为该类型不是在编译时已知的,但它会在runtime.In决定上面的例子中,我传递的值1(它可以是任何东西,则该类将相应地调用),和类test1的调用。

在这里,我将获得上线一个错误objcls.callclass()因为objcls是一个object不具有一个实例callclass()方法。

我怎么能重组这段代码? 我的目标是,如果我在提及一类getConstructorclass()方法,对象应返回,以便使用它的进一步代码来调用该类别的成员。

Answer 1:

如果你知道你的类都会有这样的方法,你应该使用他们共同的界面和遵照执行。 然后,你将用你已经确信它会工作类的工作。

它看起来像这样

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();
}
...

但它得到很快容易出错,重构将可能是一场噩梦等,但它是你的电话..

或者,你也许可以从使用的PWA的解决方案,但对我来说,似乎对于这样的基本任务不必要地复杂化。 看起来不错,所有的,但它仍然只返回类型的“对象”,所以它并没有真正解决您的具体问题。

此外,为了解决一个问题,我不知道你明白 - 你已经创建的实例,你可以返回类型的对象。 这就是为什么你不能调用这个对象上的任何具体的方法,因为首先你必须将它转换的东西,实际上有一个方法,并确保铸件可以做到的(继承等)。



Answer 2:

如果interface解决方案(见其他答案)就足够了,不要看这个答案。 当你不能用普通的基类/接口,你仍然要调用的成员,您可以使用解决方案与is关键字(检查类型)。 而不是写很多IFS为每种情况下,你可以用流利的API:

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);
    }
}

Remeber -这将是更优雅的使用通用接口(如其他答案说) -我只是另一种方式。



Answer 3:

声明你的变量动态

dynamic objcls = getconstrorclass();

使用这个会在运行时,无论确定getconstrorclass方法返回。 您可以访问该类型的任何成员,您将无法获得在编译时的错误。 但是,如果您尝试访问不存在,你会得到一个成员RuntimeBinderException在运行时。



Answer 4:

我会建议使用的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();
}


Answer 5:

不知道你想要什么,最终实现,但这个看起来像“依赖注入”工作-这里是一个很好的样本使用autofac



文章来源: Return instance using reflection in C#