有没有办法使用DLR引用C#中的方法?
在JavaScript或Python等动态语言中,我可以轻松地将方法作为参数传递给另一个方法。在C#中是静态类型语言,我要么使用需要大量转换的Delegate
类型:
public static void AddMethod(Delegate del)
{
// implementation
}
然后在我调用此方法时使用转换
static void Main(string[] args)
{
AddMethod(new Func<object, bool>(Test));
}
public static bool Test(object obj)
{
return true;
}
或者,我需要定义几十个重载来满足任何方法调用:
public static void AddMethod<TResult>(Func<TResult> method)
{
}
public static void AddMethod<T, TResult>(Func<T, TResult> method)
{
}
public static void AddMethod<T1, T2, TResult>(Func<T1, T2, TResult> method)
{
}
public static void AddMethod<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> method)
{
}
有没有更简洁的方法将参数定义为所有其他方法的占位符? (我在这里试图避免MethodInfo
或其他Reflection
内容。
我正在尝试这样的事情:
public delegate dynamic DynamicDelegate(params dynamic[] args);
public static void AddMethod(DynamicDelegate method)
{
}
但编译器似乎不接受动态声明的委托的静态类型方法!
还有其他想法吗?
答案 0 :(得分:2)
您可以使用简单的Action
void AddMethod(Action action) //or void AddMethod(Func<TResult> fxn)
{
}
并致电
AddMethod(()=>Test(obj));
或
AddMethod(()=>Test(obj1,obj2));
- 编辑 -
AddMethod(() => Math.Max(1,3));
AddMethod(() => (int)Math.Sqrt(4));
AddMethod(() => new int[]{8,5,6}.Min())
void AddMethod(Func<int> fxn)
{
int i = fxn() * fxn(); // <---
}
答案 1 :(得分:2)
由于.NET不允许具有未知参数语法的委托(这将近似C void指针,这不是您想要的类型安全语言),允许变量参数列表的最接近的事情是传递一个对象参数数组(即object MyMethod(params object[] args))
但是,由于此数组也是对象引用,因此您可以使用单个对象引用:
object MyMethod(object arg))
.NET框架也这样做,参见例如ParameterizedThreadStart delegate)
因此,基本思想是您要求用户将其代码编写为与上述签名匹配的方法,然后它可以接收任何类型或大小的任何变量参数列表。
答案 2 :(得分:0)
见下文
public delegate dynamic Reference(params dynamic[] args);
public class PassByReference
{
Reference reference;
public PassByReference(Reference reference)
{
this.reference = reference;
}
public override string ToString()
{
return this.reference().ToString();
}
}
public class Logger
{
static Dictionary<string, Logger> logFormatDict = new Dictionary<string, Logger>();
private List<LoggerDelegate> loggerDelegates = new List<LoggerDelegate>();
public static Logger GetLogger(string name)
{
if (logFormatDict.ContainsKey(name))
{
return logFormatDict[name];
}
else
{
var newLogFormat = new Logger(name, "");
logFormatDict.Add(name, newLogFormat);
return newLogFormat;
}
}
private event LoggerDelegate loggingEvent;
private Logger(string name, string format, params dynamic[] args)
{
this.Name = name;
this.format = format;
this.args = args;
}
public void AddLogger(LoggerDelegate logger)
{
if (!loggerDelegates.Contains(logger))
{
loggingEvent += logger;
loggerDelegates.Add(logger);
}
}
public void RemoveLogger(LoggerDelegate logger)
{
if (loggerDelegates.Contains(logger))
{
loggingEvent -= logger;
loggerDelegates.Remove(logger);
}
}
public void Log(string text, params dynamic[] args)
{
this.Invoke(String.Format(text, args));
}
public void Invoke(string text, params dynamic[] args)
{
loggingEvent.Invoke(this.ToString() + text, args);
}
public void SetFormat(string format, params dynamic[] args)
{
this.args = args;
this.format = format;
}
public string Name
{
get;
set;
}
string format;
dynamic[] args;
public override string ToString()
{
return String.Format(format, args);
}
}
transform: translate(0, -50%);