2

我正在尝试访问从同一父级继承的对象中在父类(在其自己的程序集中)中标记为内部的方法。

让我解释一下我想要做什么......

我想创建服务类,将带有基础列表的 IEnumberable 返回到非服务类(例如 UI),并可选择将带有基础 IQueryable 的 IEnumerable 返回给其他服务。

我编写了一些示例代码来演示我要完成的工作,如下所示。该示例不是现实生活,因此请在评论时记住这一点。

所有服务都将从这样的东西继承(仅显示相关代码):

public class ServiceBase<T>
{
    protected readonly ObjectContext _context;
    protected string _setName = String.Empty;

    public ServiceBase(ObjectContext context)
    {
        _context = context;
    }

    public IEnumerable<T> GetAll()
    {
        return GetAll(false);
    }

    //These are not the correct access modifiers.. I want something
    //that is accessible to children classes AND between descendant classes
    internal protected IEnumerable<T> GetAll(bool returnQueryable)
    {
        var query = _context.CreateQuery<T>(GetSetName());
        if(returnQueryable)
        {
            return query;
        }
        else
        {
            return query.ToList();
        }
    }

    private string GetSetName()
    {
        //Some code...
        return _setName;
    }



}

继承的服务如下所示:

public class EmployeeService : ServiceBase<Employees>
{
    public EmployeeService(ObjectContext context)
        : base(context)
    {

    }

}

public class DepartmentService : ServiceBase<Departments>
{
    private readonly EmployeeService _employeeService;

    public DepartmentService(ObjectContext context, EmployeeService employeeService) : base(context)
    {
        _employeeService = employeeService;
    }

    public IList<Departments> DoSomethingWithEmployees(string lastName)
    {
        //won't work because method with this signature is not visible to this class
        var emps = _employeeService.GetAll(true);

        //more code...
    }
}

因为父类的存在是可重用的,所以它会存在于与子服务不同的程序集中。由于 GetAll(bool returnQueryable) 被标记为内部,孩子们将无法看到彼此的 GetAll(bool) 方法,只能看到公共 GetAll() 方法。

我知道我可以为每个服务(或者可能是同一程序集中的中间父类)添加一个新的内部 GetAll 方法,以便程序集中的每个子服务可以看到彼此的方法;但这似乎没有必要,因为该功能已经在父类中可用。

例如:

    internal IEnumerable<Employees> GetAll(bool returnIQueryable)
    {
        return base.GetAll(returnIQueryable);
    }

本质上,我想要的是服务能够以 IQueryable 的形式访问其他服务方法,以便它们可以进一步细化未提交的结果,而其他所有人都可以获得普通的旧列表。

有任何想法吗?

编辑

你知道吗,我用这个玩了一些代码高尔夫很有趣......但最终我无论如何都无法使用这个方案,因为我传递的是接口,而不是类。

因此,在我的示例中,GetAll(bool returnIQueryable) 不会出现在界面中,这意味着我必须进行强制转换,这与我想要完成的事情背道而驰。

我不确定我是不是脑子里放了个屁,或者我只是太兴奋了,想得到一些我认为可以很好用的东西。无论哪种方式,感谢您的回复。

4

3 回答 3

3

公开该方法的明显答案有什么问题?

无论如何,可访问性并不安全,因此“邪恶的人”可以使用反射来绕过您放置的任何修饰符。并且由于您想从不相关的“兄弟”类中调用这些方法,因此它们应该是公共的,因为没有“兄弟”可访问性修饰符。

替代建议:应用该[assembly:InternalsVisibleTo("SomeOtherAssembly")]属性以授予其他业务域程序集对内部成员的访问权限。

请注意,这会增加维护负担(如果您重命名或添加程序集),使用“魔术字符串”,并否定 internal 的原始含义(因为所有内部成员现在对这些其他程序集也可见)。

于 2010-04-08T22:04:21.500 回答
0

当您的后代类将存在于同一个程序集中时,这会更容易。但是,当您的类位于单独的程序集中(将接口的internal关键字更改为public)时,以下“技巧”也有效,但它只会阻止在未强制转换对象时调用该方法。例如,将InheritedClass对象强制转换为 anIBaseInterface将允许任何人调用该GetValue方法。这是您无法真正阻止的事情,因为即使有一些关键字组合可以做您想做的事情,仍然有人可以通过反射调用这些方法。

internal interface IBaseInterface {
    string GetValue();
}

public abstract class MyBase : IBaseInterface {
    string IBaseInterface.GetValue()
    { return "MyBase"; }
}

public class InheritedClass : MyBase {
    public void PrintValue(IBaseInterface someclass)
    { Console.WriteLine(someclass.GetValue()); }
}
于 2010-04-08T22:10:06.690 回答
0

也许我遗漏了一些东西,但您应该能够将其标记为protected internal并实现您的目标。

namespace Foo
{
    class A
    {
        protected internal void D() { Console.WriteLine(this.ToString() + " says 'Blah'"); }
    }
}

namespace Bar
{
    class B : Foo.A 
    {
        public B()
        {
        }
    }
}

namespace Baz
{
    class C : Foo.A
    {
        public C()
        {
            D();
            Bar.B b = new Bar.B();
            b.D();

            Foo.A a = new Foo.A();
            a.D();
        }
    }
}

查看输出

Baz.C c = new Baz.C();

这都是合法的代码。Foo.A 是基础,Bar.B 和 Baz.C 继承自 Foo.A。void D 是 A 的受保护内部成员。Baz.C 可以按预期调用 D(),也可以创建 Bar.B 和 Foo.A 的实例并调用它们的 D() 方法。

protected internal成员对任何程序集中的所有后代类以及与基相同的程序集内的所有类都是可见的。可访问性在这些范围之外结束。与孩子在同一程序集中的非后代班级将无法看到该成员。

于 2010-04-08T23:59:36.847 回答