Dynamically replace the contents of a C# method?

后端 未结 10 2282
面向向阳花
面向向阳花 2020-11-22 16:09

What I want to do is change how a C# method executes when it is called, so that I can write something like this:

[Distributed]
public DTask Solve         


        
10条回答
  •  南笙
    南笙 (楼主)
    2020-11-22 16:18

    I know it is not the exact answer to your question, but the usual way to do it is using factories/proxy approach.

    First we declare a base type.

    public class SimpleClass
    {
        public virtual DTask Solve(int n, DEvent callback)
        {
            for (int m = 2; m < n - 1; m += 1)
                if (m % n == 0)
                    return false;
            return true;
        }
    }
    

    Then we can declare a derived type (call it proxy).

    public class DistributedClass
    {
        public override DTask Solve(int n, DEvent callback)
        {
            CodeToExecuteBefore();
            return base.Slove(n, callback);
        }
    }
    
    // At runtime
    
    MyClass myInstance;
    
    if (distributed)
        myInstance = new DistributedClass();
    else
        myInstance = new SimpleClass();
    

    The derived type can be also generated at runtime.

    public static class Distributeds
    {
        private static readonly ConcurrentDictionary pDistributedTypes = new ConcurrentDictionary();
    
        public Type MakeDistributedType(Type type)
        {
            Type result;
            if (!pDistributedTypes.TryGetValue(type, out result))
            {
                if (there is at least one method that have [Distributed] attribute)
                {
                    result = create a new dynamic type that inherits the specified type;
                }
                else
                {
                    result = type;
                }
    
                pDistributedTypes[type] = result;
            }
            return result;
        }
    
        public T MakeDistributedInstance()
            where T : class
        {
            Type type = MakeDistributedType(typeof(T));
            if (type != null)
            {
                // Instead of activator you can also register a constructor delegate generated at runtime if performances are important.
                return Activator.CreateInstance(type);
            }
            return null;
        }
    }
    
    // In your code...
    
    MyClass myclass = Distributeds.MakeDistributedInstance();
    myclass.Solve(...);
    

    The only performance loss is during construction of the derived object, the first time is quite slow because it will use a lot of reflection and reflection emit. All other times, it is the cost of a concurrent table lookup and a constructor. As said, you can optimize construction using

    ConcurrentDictionary>.
    

提交回复
热议问题