C# 在C中作为参数传递方法的动态委托#
有没有办法使用DLR引用C#中的方法 在JavaScript或Python等动态语言中,我可以轻松地将一个方法作为参数传递给另一个方法。在C#静态类型语言中,我要么使用C# 在C中作为参数传递方法的动态委托#,c#,dynamic,C#,Dynamic,有没有办法使用DLR引用C#中的方法 在JavaScript或Python等动态语言中,我可以轻松地将一个方法作为参数传递给另一个方法。在C#静态类型语言中,我要么使用Delegatetype,这需要大量转换: public static void AddMethod(Delegate del) { // implementation } 然后在我调用这个方法时使用casting static void Main(string[] args) { AddMethod(new F
Delegate
type,这需要大量转换:
public static void AddMethod(Delegate del)
{
// implementation
}
然后在我调用这个方法时使用casting
static void Main(string[] args)
{
AddMethod(new Func<object, bool>(Test));
}
public static bool Test(object obj)
{
return true;
}
但是编译器似乎不接受动态声明委托的静态类型化方法
还有其他想法吗?您可以使用简单的
操作
void AddMethod(Action action) //or void AddMethod(Func<TResult> fxn)
{
}
或
--编辑--
AddMethod(()=>Math.Max(1,3));
AddMethod(()=>(int)Math.Sqrt(4));
AddMethod(()=>newint[]{8,5,6}.Min())
void AddMethod(Func fxn)
{
int i=fxn()*fxn();//由于.NET不允许具有未知参数语法的委托(这将近似于C void指针,这在类型安全语言中不是您想要的),因此允许变量参数列表的最接近的方法是传递对象参数数组(即对象MyMethod(params object[]args))
但是,由于此数组也是一个对象引用,因此只需一个对象引用即可:
object MyMethod(object arg))
NET framework也会这样做,请参见
因此,基本思想是,您要求用户将其代码编写为与上述签名匹配的方法,反过来,它可以接收任何类型或大小的参数的任何变量列表。请参见下文
Logger coreLogger;
Logger coreErrorLogger;
public Core()
{
PassByReference timestamp = new PassByReference(Timestamp);
coreLogger = Logger.GetLogger("LiTHiuM Core");
coreLogger.SetFormat("[{0}][LiTHiuM Core]: ", timestamp);
coreLogger.AddLogger(Log);
coreErrorLogger = Logger.GetLogger("LiTHiuM Core Error");
coreErrorLogger.SetFormat("[{0}][LiTHiuM Core (ERROR)]: ", timestamp);
coreErrorLogger.AddLogger(Error);
}
public string Timestamp(params dynamic[] args)
{
return DateTime.Now.ToString();
}
公共类记录器
{
静态字典logFormatDict=新字典();
私有列表loggerDelegates=新列表();
公共静态记录器GetLogger(字符串名称)
{
if(logFormatDict.ContainsKey(名称))
{
返回logFormatDict[name];
}
其他的
{
var newLogFormat=新记录器(名称“”);
添加(名称,newLogFormat);
返回newLogFormat;
}
}
私人事件日志代理日志事件;
专用记录器(字符串名称、字符串格式、参数dynamic[]args)
{
this.Name=Name;
this.format=格式;
this.args=args;
}
公共无效添加记录器(LoggerDelegate记录器)
{
如果(!loggerDelegates.Contains(记录器))
{
loggingEvent+=记录器;
添加(记录器);
}
}
公共无效删除记录器(LoggerDelegate记录器)
{
if(loggerDelegates.Contains(记录器))
{
loggingEvent-=记录器;
记录器。移除(记录器);
}
}
公共作废日志(字符串文本,参数动态[]参数)
{
this.Invoke(String.Format(text,args));
}
公共void调用(字符串文本,参数动态[]参数)
{
loggingEvent.Invoke(this.ToString()+text,args);
}
public void SetFormat(字符串格式,参数dynamic[]args)
{
this.args=args;
this.format=格式;
}
公共字符串名
{
得到;
设置
}
字符串格式;
动态[]args;
公共重写字符串ToString()
{
返回String.Format(格式,args);
}
}
使用Action意味着我实际上在调用该方法,但是我要寻找的是将该方法作为参数传递,我需要获取该方法的引用以供进一步使用callback@KamyarNazeri查看我的编辑。使用Action意味着我实际上调用的方法不完全是
,除非您显式地调用它这正是我所说的“定义几十个重载”的意思,这样我就必须定义大量的重载来满足任何具有signature@KamyarNazeri我不明白。例如,在第二部分中,你可以传递任何返回int的函数。这个实现对于int来说实际上是正确的,那么一个带参数的方法呢?一个带2个参数或3或4个参数的方法?我试着抽象为了能够用任何签名注册任何方法,这样我必须定义许多采用Func的方法,ActionSay也一样,你可以传递一个“动态委托”对于另一个方法,另一个方法将如何处理它?如果你想调用它,你要么必须知道该方法的签名是什么样子的,要么你还必须隐式地提供参数值,这样“另一个方法”就不必知道它们了(这通常是通过lambda完成的,参见L.B.的帖子)“其他方法"只传递委托?你是对的,我试图做的是提取签名和注册方法的信息,以便进一步调用。我试图创建一个简单的计算,或者更好地说,动态代码生成,让用户使用预定义的方法编写自己的C代码。没错,但是谁会参与ke传递的方法?是您的代码调用用户提供的代码,就像它是一个插件一样?还是用户自己的代码,其中您的代码只是作为代理的临时存储,直到允许用户使用它?感谢您提供此代码片段,它可能会提供一些有限的、即时的帮助。a将大大改进它的长期价值在于说明为什么这是一个很好的问题解决方案,并使它对未来读者提出其他类似问题更有用。请在您的回答中添加一些解释,包括您所做的假设。
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(); // <---
}
object MyMethod(object arg))
Logger coreLogger;
Logger coreErrorLogger;
public Core()
{
PassByReference timestamp = new PassByReference(Timestamp);
coreLogger = Logger.GetLogger("LiTHiuM Core");
coreLogger.SetFormat("[{0}][LiTHiuM Core]: ", timestamp);
coreLogger.AddLogger(Log);
coreErrorLogger = Logger.GetLogger("LiTHiuM Core Error");
coreErrorLogger.SetFormat("[{0}][LiTHiuM Core (ERROR)]: ", timestamp);
coreErrorLogger.AddLogger(Error);
}
public string Timestamp(params dynamic[] args)
{
return DateTime.Now.ToString();
}
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);
}
}