2016-04-21 9 views
0

Ich möchte statische Funktionen über DynamicObject ausführen, aber ich weiß nicht, wie saveOperation ausführen, ohne den Klassennamen typeof(Test1) oder typeof(Test2) anzugeben. Wie relise das besser?Dynamisches Objekt. Wie Funktion durch TryInvoke ausführen?

Zum Beispiel

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){ ...} 
} 

Zweite Art und Weise definiert statische Funktion mit dem Attribut (von Carnifex angeboten)

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

und bekommen Typ

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

Antwort

2

Sie könnten einige Attribute verwenden und zB . [DynFuncMemberAttribute] an die Klasse oder an die Methode selbst.

dann innerhalb TryInvoke (oder Konstruktor) erhalten alle Arten/Methoden mit diesem Attribut gekennzeichnet, einige Karte/cache bauen und voila :)


Edit: das ist dieses Attribut Anwendungsbeispiel. Denken Sie daran, dass BuildCache() eine Ausnahme auslöst, wenn zwei Methoden mit demselben Namen gefunden werden.

[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"); 
    } 
} 
+0

Vielen Dank für die Antwort Ich bearbeite meine Frage mit Ihrer Idee – askeet