5

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

しかし、コンパイラは動的に宣言されたデリゲートに対して静的に型付けされたメソッドを受け入れていないようです!

他に何か考えはありますか?

4

3 に答える 3

4

シンプルなものが使えます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();  // <---
}
于 2012-11-24T11:57:21.633 に答える
2

.NETでは不明なパラメーター構文を持つデリゲートは許可されないため(これはC voidポインターを近似しますが、これはタイプセーフ言語では必要ありません)、可変引数リストを許可する最も近い方法は配列を渡すことです。オブジェクト引数の数(つまりobject MyMethod(params object[] args))
この配列はオブジェクト参照でもあるため、単一のオブジェクト参照で十分です。

object MyMethod(object arg))

.NET Frameworkもこれを行います。たとえば、ParameterizedThreadStartデリゲートを参照してください)

したがって、基本的な考え方は、ユーザーが上記の署名に一致するメソッドとしてコードを記述し、次に、任意のタイプまたはサイズの引数の任意の変数リストを受け取ることができるようにすることを要求することです。

于 2012-11-24T12:53:07.557 に答える
0

下記参照

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

于 2020-06-01T23:32:43.987 に答える