有人创建了一个开源的动态.net类,用于在另一个类上公开私有函数/属性吗?



如果是的话,我非常想使用它。有人有什么建议吗?

我的目标是在我的测试解决方案中去掉_accessor项目的需要。我认为,如果我创建一个动态类,应该可以记录应用于它的函数,然后使用反射在另一个对象上重播这些函数。通过反射,我们可以调用私有函数。(我想要c++的#define private public的c#变体)

我想我可以自己做这件事,但是如果我可以重用一些代码,为什么要这样做呢?

如果您想将此用于单元测试,请考虑更改您的单元测试方法。如果您深入到每个私有方法,您的测试将与实际实现紧密耦合。

使用这种方法的常见问题有

  • 非常脆弱,难以维护的测试
  • 您的测试很可能反映您的应用程序的行为和代码
  • 类的基本行为并不明显,因为有几十个测试描述了每个细节

每次你必须重构一些代码时,你也必须改变一堆测试。这将给重构带来巨大的障碍,因为修复所有破坏的测试需要花费时间和痛苦。您甚至冒着创建不希望的行为的风险,因为您必须更改如此多的测试,从而更改了原始行为。

我建议编写测试来测试类的行为。如果你改变了实现这种行为的方式,你根本不会破坏测试,并且得到了重构没有改变整体行为的确认。

你的测试将更清晰,并指定你的设计中真正重要的部分。这在重构时很有帮助,或者如果有人(甚至可能是几个月后的您)不得不再次进入代码。

您可以使用扩展动态访问每个私有函数。

public static class ObjectEx
    {
        public static object CallPrivateFunc(this object obj,string funcName, params object[] args)
        {
            const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod;
            return obj.GetType().InvokeMember(funcName, bindingFlags, null, obj, args);
        }
    }

用法:

public class MyClass
    {
        private void  MyFunc(int a,string c)
        {
            Trace.WriteLine("MyFunc called a:" + a + " c:" + c);
        }
    }
...
myClass.CallPrivateFunc("MyFunc", 10, "c");
...

我试着自己创建这个类,这段代码是否适用于方法调用:

public class UnPrivatify : DynamicObject
{
    private object _obj;
    public UnPrivatify(object obj)
    {
        _obj = obj;
    }
    public override bool TryInvokeMember(
        InvokeMemberBinder binder,
        Object[] args,
        out Object result)
    {
        Type t = _obj.GetType();
        result = t.InvokeMember(binder.Name,
            System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public,
            null,
            _obj,
            args);
        return true;
    }
}

apache许可的即兴接口具有静态函数,这些函数使用DLR来调用方法或属性,无论它是否通过binder.name私有。在DynamicObject内部调用它们应该很容易。

http://code.google.com/p/impromptu-interface/wiki/UsageReallyLateBinding

编辑:

在最新发布的4.0版本中,有一个抽象类ImpromptuForwarder,如果你创建一个普通的子类而不做任何更改,它将转发对目标中的私有方法/属性的动态调用。

最新更新