有人创建了一个开源动态 .NET 类来公开另一个类上的私有函数/属性吗?

发布于 2024-10-31 14:28:15 字数 224 浏览 1 评论 0原文

如果是这样,我非常想使用它。有人有任何指点吗?

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

我想我自己就能做到这一点,但如果我可以重用一些代码,为什么还要这么做呢。

And if so, I would very much like to use it. Does anybody have any pointers?

My goal is to remove the need for _accessor projects in my test solution. I figured that if I created a dynamic class, it should be possible to record what functions are applied to it and then replay these functions, using reflection, on another object. And with reflection we can call private functions. (I want the C# variant of C++'s #define private public.)

I think I would be able to do this myself, but why do it if I can reuse some code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

青芜 2024-11-07 14:28:15

如果您想将其用于单元测试,请考虑更改单元测试的方法。如果您深入研究每个私有方法,您的测试与实际实现会非常紧密地耦合。

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

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

每次您必须重构有些代码你还必须更改一堆测试。这将为重构造成巨大障碍,因为修复所有破坏测试需要时间和痛苦。您甚至可能冒着产生不良行为的风险,因为您必须更改大量测试,从而导致原始行为发生改变。

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

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

If you want to use this for unit testing consider to change your approach to unit testing. If you go down to every private method your tests are coupled very tight to the actual implementation.

Common problems using this approach are

  • Very fragile and hard to maintain tests
  • Your tests are very likely to mirror the behavior and code of your application
  • Essential behavior of your classes isn't obvious because of dozens of tests describing every detail

Every time you have to refactor some code you will have to change a bunch of tests, too. This will create a huge barrier to refactoring because of the time and pain it takes to fix all breaking tests. You even risk creating undesired behavior because you have to change so many tests that the original behavior is changed.

I would recommend writing tests testing the behavior of your classes. If you change the way this behavior is achieved you won't break tests at all and get the confirmation that your refactoring did not change the overall behavior.

Your tests will be much clearer and specify the really important parts of your design. This helps when refactoring, or if some one (may be even you after a couple of months) has to get into the code again.

指尖凝香 2024-11-07 14:28:15

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

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");
...

You can use extensions to access dynamically to every private functions.

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

There the usage:

public class MyClass
    {
        private void  MyFunc(int a,string c)
        {
            Trace.WriteLine("MyFunc called a:" + a + " c:" + c);
        }
    }
...
myClass.CallPrivateFunc("MyFunc", 10, "c");
...
怎言笑 2024-11-07 14:28:15

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

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

I tried to create the class myself, is this code sort of works for method calls:

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;
    }
}
和影子一齐双人舞 2024-11-07 14:28:15

apache 许可的Impromptu Interface 具有使用 DLR 调用方法或属性的静态函数无论它是否是私有的,都通过binder.name 进行。调用 DynamicObject 内部的那些应该非常容易。

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

编辑

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

The apache licensed Impromptu Interface has static functions that use the DLR to invoke methods or properties regards of whether it's private or not via binder.name. It should be pretty easy to call those inside of a DynamicObject.

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

Edit:

In the latest released version 4.0, there is a abstract class ImpromptuForwarder that if you make a plain subclass with no changes would forward dynamic calls to private methods/properties in the target.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文