Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中使用反射返回实例#_C#_Asp.net_Reflection - Fatal编程技术网

C# 在C中使用反射返回实例#

C# 在C中使用反射返回实例#,c#,asp.net,reflection,C#,Asp.net,Reflection,下面给出了我试图返回类实例的示例代码 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

下面给出了我试图返回类实例的示例代码

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
是一个
object
实例,它没有
callclass()
方法

如何重构这段代码?我的目标是,如果我在
getConstructorclass()
方法中提到一个类,那么应该返回一个对象,以便在进一步的代码中使用它来调用该类的成员。

将变量声明为动态变量


无论
getconstrorclass
方法返回什么,都将在运行时使用该函数来确定。您可以访问该类型的任何成员,并且在编译时不会出现任何错误。但是,如果您试图访问一个不存在的成员,您将在运行时得到一个
RuntimeBinderException

如果您知道您的类将具有此方法,您应该为它们使用一个公共接口,并相应地实现它。然后,您将使用已确保其正常工作的类

看起来是这样的

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 object。这就是为什么你不能在这个对象上调用任何特定的方法,因为首先你必须将它强制转换为某个实际拥有该方法的对象,并确保可以执行强制转换(继承等)。

不确定你最终想要实现什么,但这看起来像是“依赖注入”的工作-这里是一个使用的示例,我建议使用
接口
,并将您可以通过这种方式实例化的类限制为仅实现该接口的类

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();
}
公共接口IMyInterface
{
void callclass();
}
公共getConstructorClass()
{
T例;
Type Type=Type.GetType(“test1”);
//如果无法将对象转换为类型T,则实例将为null。
instance=Activator.CreateInstance(类型)作为T;
返回T;
}
IMyInterface objcls=getConstructorClass();
if(null!=objcls)
{
callclass();
}

如果
接口
解决方案(见其他答案)足够,不要看这个答案。当您不能使用公共基类/接口并且仍然需要调用成员时,您可以使用带有
is
关键字(和检查类型)的解决方案。您可以使用fluent 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();
objectobj=this.getConstructorclass();
obj.StronglyInvoke()
.When(value=>Console.WriteLine(“将{0}设为int”,value))
.When(value=>Console.WriteLine(“将{0}作为字符串,value))
.OnFail(()=>Debug.Write(“无句柄”))
.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);
    }
}
公共类GenericCaller
{
私有IList调用程序=新列表();
私有只读对象目标;
私人行动;
公共GenericCaller(对象目标)
{
if(target==null)
{
抛出新的ArgumentNullException(“目标”);
}
this.target=目标;
}
公共GenericCaller OnFail(操作失败)
{
this.failAction=失败;
归还这个;
}
public GenericCaller When(然后执行操作)
{
if(then==null)
{
抛出新的ArgumentNullException(“then”);
}
var invoker=new GenericInvoker(然后是this.target);
this.invokers.Add(invoker);
归还这个;
}
公共无效调用()
{
if(this.invokers.Any(invoker=>invoker.Invoke())
{
返回;
}
if(this.failAction==null)
{
抛出新的InvalidOperationException(“未找到处理程序”);
}
这个.failAction();
}
公共抽象类GenericInvoker
{
受保护的只读对象目标;
受保护的GenericInvoker(对象目标)
{
this.target=目标;
}
公共抽象bool Invoke();
}
公共类GenericInvoker:GenericInvoker
{
私人只读操作;
公共GenericInvoker(对象目标,然后操作)
:基本(目标)
{
this.then=then;
}
公共重写bool Invoke()
{
if(this.target.GetType()==typeof(T))
{
然后((T)这个目标);
返回true;
}
返回false;
}
}
}
公共静态类扩展
{
公共静态GenericCaller StronglyInvoke(此对象为o)
{
返回新的GenericCaller(o);
}
}

请记住-使用通用界面(正如其他答案所说)会更优雅-我的方法是唯一的替代方法。

我可以问一下,通过这样做,您想要实现什么吗?(顺便说一句,从你的例子中你知道
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);
    }
}