动态对象。如何通过 TryInvoke 执行函数?

DynamicObject. How execute function through TryInvoke?

我想通过 DynamicObject 执行静态函数,但我不知道如何在不指定 class 名称 typeof(Test1)typeof(Test2) 的情况下执行 saveOperation。如何更好地依赖这个?

例如

class DynObj : DynamicObject
{
    GetMemberBinder saveOperation;
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        saveOperation = binder;
        result = this;
        return true;
    }

    public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
    {
        Type myType = typeof(Test1 or Test2 or ....);

        result = myType.GetMethod(saveOperation.Name).Invoke(null, args);
        return true;
    }
 }
 class Program
    {
        static void Main(string[] args)
        {
            dynamic d1 = new DynObj();
            d1.func1(3,6);
            d1.func2(3,6);
        }
  }

 class Test1
 {
    public static void func1(int a, int b){...}
 }

 class Test2
 {
    public static void func2(int a, int b){ ...}
 }

第二种方式定义带有属性的静态函数(由 Carnifex 提供)

 class Test3
 {
    [DynFuncMemberAttribute] 
    public static void func3(int a, int b){...}
 }

并获取类型

     public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
    {
        Type myType = null;
        foreach (Type types in Assembly.GetExecutingAssembly().GetTypes())
        {
            foreach (MethodInfo mi in types.GetMethods())
            {
                foreach (CustomAttributeData cad in mi.CustomAttributes)
                {
                    if (cad.AttributeType == typeof(DynFuncMemberAttribute))
                    {
                        myType = types;
                        break;
                    }
                }
            }
        }

        result = (myType != null)? myType.GetMethod(saveOperation.Name).Invoke(null, args): null;
        return myType != null;
    }

您可以使用一些属性并设置例如。 [DynFuncMemberAttribute] 到 class 或其自身的方法。

然后在 TryInvoke(或构造函数)中获取所有标有此属性的 types/methods,构建一些 map/cache 瞧 :)


编辑:这是使用此属性的示例。请记住,如果找到两个具有相同名称的方法,BuildCache() 将抛出异常。

[AttributeUsage(AttributeTargets.Method)]
class DynFuncMemberAttribute : Attribute
{
}

class DynObj : DynamicObject
{
    Dictionary<string, MethodInfo> cache;
    GetMemberBinder saveOperation;
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        saveOperation = binder;
        result = this;
        return true;
    }

    public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
    {
        if (cache == null)
            cache = BuildCache();

        MethodInfo mi;
        if (cache.TryGetValue(saveOperation.Name, out mi))
        {
            result = mi.Invoke(null, args);
            return true;
        }

        result = null;
        return false;
    }

    private Dictionary<string, MethodInfo> BuildCache()
    {
        return Assembly.GetEntryAssembly()
            .GetTypes()
            .SelectMany(t => t.GetMethods(BindingFlags.Public | BindingFlags.Static))
            .Where(mi => mi.GetCustomAttribute<DynFuncMemberAttribute>() != null)
            .ToDictionary(mi => mi.Name);
    }
}

class Program
{
    static void Main(string[] args)
    {
        dynamic d1 = new DynObj();
        d1.func1(3, 6);
        d1.func2(3, 6);
    }
}

class Test1
{
    [DynFuncMember]
    public static void func1(int a, int b)
    {
        Console.WriteLine("func1");
    }
}

class Test2
{
    [DynFuncMember]
    public static void func2(int a, int b)
    {
        Console.WriteLine("func2");
    }
}