如何使用另一个对象上存在的方法动态扩展c#对象?

时间:2014-04-02 03:00:19

标签: c# reflection

假设我有一个对象a,它是A类:

abstract class A {
    public abstract SomeType SomeMethod(int i)
    public abstract SomeType SomeOtherMethod()
}

我可以/如何创建B类的对象b - 在运行时可以使用任何对象(比如说A),并将其包装起来:

class B {
   public void Wrap(object someObject) {}
}

这样我就可以编写以下代码:

var a = Factory.BuildAn<A>();
var b = new B();
b.Wrap(a);
b.SomeMethod(1);

2 个答案:

答案 0 :(得分:3)

我不确定你用这个问题试图解决什么问题,但这就是你问的问题。

class MyClass
{
    public int IntValue { get; set; }

    public string SomeMethod(int i)
    {
        return i.ToString();
    }
    public string SomeOtherMethod()
    {
        return "Hello";
    }
}

class Wrapper : DynamicObject
{
    private object wrappedObject;

    public Wrapper(object wrappedObject)
    {
        this.wrappedObject = wrappedObject;
    }

    private void Wrap(object someObject)
    {
        wrappedObject = someObject;
    }


    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        PropertyInfo prop = wrappedObject.GetType()
            .GetProperty(binder.Name, BindingFlags.Instance | BindingFlags.Public);
        if (prop == null)
        {
            result = null;
            return false;
        }

        result = prop.GetValue(wrappedObject, null);
        return true;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        PropertyInfo prop = wrappedObject.GetType()
            .GetProperty(binder.Name, BindingFlags.Instance | BindingFlags.Public);
        if (prop == null)
        {
            return false;
        }

        prop.SetValue(wrappedObject, value);
        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        MethodInfo method = wrappedObject.GetType()
            .GetMethod(binder.Name, BindingFlags.Instance | BindingFlags.Public);
        if (method == null)
        {
            result = null;
            return false;
        }

        result = method.Invoke(wrappedObject, args);
        return true;
    }
}

MyClass a = new MyClass();
dynamic d = new Wrapper(a);
d.IntValue = 5;
string s = d.SomeOtherMethod();
Console.WriteLine(a.IntValue);

答案 1 :(得分:2)

是的,您可以在C#中使用动态类型。 B类看起来像这样,你将完全按照你在问题中使用它的方式使用它。

class B : DynamicObject
{
    object _object;
    public void Wrap(object someObject)
    {
        _object = someObject;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        try
        {
            result = _object.GetType().InvokeMember(
                binder.Name,
                BindingFlags.InvokeMethod |
                BindingFlags.Public |
                BindingFlags.Instance,
                null, _object, args);
                return true;
        }
        catch
        {
            result = null;
            return false;
        }
    }
}