我有一個動態的變量C#動態執行函數的名字?
dynamic d = GetSomeObject();
有時,在未來,用戶給我一個函數來執行(其name
)如"UsersGetAll"
所以我需要做的是這樣的:d.UsersGetAll()
我可以用反射來做到這一點。但我想使用DLR。
做這個的唯一解決方案是從DynamicObject
繼承MyObject
,然後執行TryInvokeMember
?
如果我無法控制課程該怎麼辦?
我有一個動態的變量C#動態執行函數的名字?
dynamic d = GetSomeObject();
有時,在未來,用戶給我一個函數來執行(其name
)如"UsersGetAll"
所以我需要做的是這樣的:d.UsersGetAll()
我可以用反射來做到這一點。但我想使用DLR。
做這個的唯一解決方案是從DynamicObject
繼承MyObject
,然後執行TryInvokeMember
?
如果我無法控制課程該怎麼辦?
正如Jon指出的那樣,如果您懷疑類型是在運行時通過DLR提供方法,在最簡單的情況下,反思會更容易。
dynamic
僅用於知道方法名稱但不知道目標的情況。如果你不知道方法名稱,它就是比較費力的。棘手的問題也許在於確保您保持呼叫站點的地位,以便可以重複使用(這是DLR保持性能的方式)。一個厚顏無恥的方式將是一個靜態的工具類,跟蹤調用的方法。這裏有一個例子 - 請注意,它得到多混亂,如果你需要處理的參數:
using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections;
using System.Runtime.CompilerServices;
public class Foo
{
public object Bar() { return "I was here"; }
}
static class Program
{
static void Main()
{
object obj = new Foo();
object result = DynamicCallWrapper.Invoke(obj, "Bar");
Console.WriteLine(result);
}
}
static class DynamicCallWrapper
{
// Hashtable has nice threading semantics
private static readonly Hashtable cache = new Hashtable();
public static object Invoke(object target, string methodName)
{
object found = cache[methodName];
if (found == null)
{
lock (cache)
{
found = cache[methodName];
if(found == null)
{
cache[methodName] = found = CreateCallSite(methodName);
}
}
}
var callsite = (CallSite<Func<CallSite, object,object>>)found;
return callsite.Target(callsite, target);
}
static object CreateCallSite(string methodName)
{
return CallSite<Func<CallSite, object, object>>.Create(
Binder.InvokeMember(
CSharpBinderFlags.None, methodName, null, typeof(object),
new CSharpArgumentInfo[] {
CSharpArgumentInfo.Create(
CSharpArgumentInfoFlags.None, null) }));
}
}
我可以用反射來做到這一點。但我想使用DLR。
爲什麼?假設這是一個實際上不會動態響應的「正常」對象,反射將成爲這裏最簡單的方法。
C#4中的dynamic
功能(根據語言功能)在這裏完全沒有任何幫助。它只允許在C#源代碼內動態綁定成員名稱。
現在你能:
CSharpCodeProvider
以相關方法名稱使用dynamic
編譯一些C#代碼,然後執行該代碼。d.UsersGetAll()
調用生成的代碼,並基本上模擬。所有這些選項都可能比反射更困難,如果所有你想要它,所以調用一個「普通」對象的「正常」方法,並且你恰好只知道執行時的名字。
什麼是想要使用DLR的原因是什麼? AFAIK「動態」語言功能旨在簡化對未知對象的已知方法調用。也許在運行時生成由Roslyn編譯的代碼? – flindeberg