C# 是否可以创建只能由某些对象创建的类?

C# 是否可以创建只能由某些对象创建的类?,c#,object,inheritance,C#,Object,Inheritance,假设我有一个对象类(widgetBlue)。此对象类实现接口(iWidgetBlue),并从抽象类(widget)继承widgetBlue没有显式编码的构造函数,并且具有对其执行操作所需的信息 我希望能够在WidgetService中创建widgetBlue的实例,并将其返回给使用者,以便使用者可以使用它,但不允许使用者创建widgetBlue的实例WidgetService需要能够创建新的widgetBlue并实例化其属性 所以这没关系: WidgetBlue retVal = SomeRem

假设我有一个对象类(
widgetBlue
)。此对象类实现接口(
iWidgetBlue
),并从抽象类(
widget
)继承
widgetBlue
没有显式编码的构造函数,并且具有对其执行操作所需的信息

我希望能够在
WidgetService
中创建
widgetBlue
的实例,并将其返回给使用者,以便使用者可以使用它,但不允许使用者创建
widgetBlue
的实例
WidgetService
需要能够创建新的
widgetBlue
并实例化其属性

所以这没关系:

WidgetBlue retVal = SomeRemoteMethodThatReturnsAWidgetBlue();
但这并不好:

WidgetBlue retVal = new WidgetBlue();
编辑:此外,小部件对象都在它们自己的项目中,并且被消费者和服务引用


我该怎么做?

如果我正确理解了您的问题,您可以在
WidgetBlue
中创建一个无参数构造函数,并将其设置为具有
内部
访问修饰符。这样,您只能从同一程序集中的类(例如您的
WidgetService
类)创建新实例,而不能从我假设是外部程序集的使用者创建新实例。

如果我正确理解您的问题,您可以在
WidgetBlue
中创建一个无参数构造函数,并将其设置为具有
内部
访问修饰符。这样,您只能从同一程序集中的类创建新实例(例如,
WidgetService
class)而不是从您的使用者那里,我假设它是一个外部程序集。

更好的方法是使用接口,以便从使用者中抽象出具体类,甚至在将具体类标记为内部时隐藏。接口是合同,因此没有接口实例的概念/ie.接口构造函数

你的例子就是

internal class WidgetBlue : IWidgetBlue {}

IWidgetBlue retVal = SomeRemoteMethodThatReturnsAIWidgetBlue();
这是不可能的

IWidgetBlue retVal = new IWidgetBlue();

它还允许您在将来更改底层实现或根据需要扩展它。

更好的方法是使用接口,以便从使用者中抽象出具体类,甚至在将具体类标记为内部时隐藏该类。接口是合同,因此没有接口实例的概念/ie.接口构造函数

你的例子就是

internal class WidgetBlue : IWidgetBlue {}

IWidgetBlue retVal = SomeRemoteMethodThatReturnsAIWidgetBlue();
这是不可能的

IWidgetBlue retVal = new IWidgetBlue();

它还允许您在将来更改基础实现或根据需要扩展它。

您可以使用生成器模式:

public Builder
{
    bool _prop = false;
    public Builder WithProperty(bool prop)
    {
        _prop = prop; 
         return this;
    }
    public Widget Build(){ 
        if(prop)
           return new FooWidget();
        else 
           return new BarWidget();
    }   
}

public abstract class Widget()
{
}

public class FooWidget: Widget{}
public class BarWidget: Widget{}

您无法实例化抽象小部件,并且您将更高实现的实际选择隐藏在抽象后面

您可以使用构建器模式执行此操作:

public Builder
{
    bool _prop = false;
    public Builder WithProperty(bool prop)
    {
        _prop = prop; 
         return this;
    }
    public Widget Build(){ 
        if(prop)
           return new FooWidget();
        else 
           return new BarWidget();
    }   
}

public abstract class Widget()
{
}

public class FooWidget: Widget{}
public class BarWidget: Widget{}

您无法实例化抽象小部件,并且您将更高实现的实际选择隐藏在抽象后面

我通常通过在其他程序集中隐藏具体类来完成类似的工作。使
WidgetBlue
成为一个内部类,然后您可以从创建
IWidget
s的
WidgetFactory
中提供它的实例(您可以有一个
BuildBlue()
方法,如果需要,您可以轻松地扩展它,以便稍后也提供红色的)。这将客户机与您的具体实现完全分离。这叫做界面分离原理

namespace Widgets
{
    public interface IWidget
    {
    }

    internal abstract class Widget : IWidget
    {
    }

    internal class BlueWidget : Widget
    {
    }

    public class WidgetFactory
    {
        public IWidget BuildBlue()
        {
            return new BlueWidget();
        }
    }
}
在其他一些项目中:

using Widgets;

namespace Client
{
    public class Client
    {
        public static void Main(string[] args)
        {
            IWidget blueWidget = new WidgetFactory().BuildBlue();
            IWidget otherBlueWidget = new BlueWidget(); // doesn't compile
        }
    }
}

我通常通过在其他程序集中隐藏具体类来完成类似的工作。使
WidgetBlue
成为一个内部类,然后您可以从创建
IWidget
s的
WidgetFactory
中提供它的实例(您可以有一个
BuildBlue()
方法,如果需要,您可以轻松地扩展它,以便稍后也提供红色的)。这将客户机与您的具体实现完全分离。这叫做界面分离原理

namespace Widgets
{
    public interface IWidget
    {
    }

    internal abstract class Widget : IWidget
    {
    }

    internal class BlueWidget : Widget
    {
    }

    public class WidgetFactory
    {
        public IWidget BuildBlue()
        {
            return new BlueWidget();
        }
    }
}
在其他一些项目中:

using Widgets;

namespace Client
{
    public class Client
    {
        public static void Main(string[] args)
        {
            IWidget blueWidget = new WidgetFactory().BuildBlue();
            IWidget otherBlueWidget = new BlueWidget(); // doesn't compile
        }
    }
}

更正:没有构造函数。很抱歉我编辑了我的问题以反映这一点。只需创建一个无参数构造函数,然后使用
内部
访问修饰符。请参阅我的更新…Hrm,我要保护的小部件类位于它自己的项目和命名空间中,由远程方法引用,并且将由使用者引用。使维护代码更容易。这已经达到了预期的效果,只是我不能在返回对象的远程服务中实例化它。读这篇文章(或者自己用谷歌搜索):没有什么可以阻止别人这么做。就像没有什么可以阻止人们反向工程你的代码,看看你的魔法是如何工作的一样,事实上,像IL Spy和Redgate的.NET Reflector这样的工具就是这样做的——使用反射。只是永远不要在代码中隐藏任何秘密,比如加密/解密密钥:)更正:没有构造函数。很抱歉我编辑了我的问题以反映这一点。只需创建一个无参数构造函数,然后使用
内部
访问修饰符。请参阅我的更新…Hrm,我要保护的小部件类位于它自己的项目和命名空间中,由远程方法引用,并且将由使用者引用。使维护代码更容易。这已经达到了预期的效果,只是我不能在返回对象的远程服务中实例化它。读这篇文章(或者自己用谷歌搜索):没有什么可以阻止别人这么做。就像没有什么可以阻止人们反向工程你的代码,看看你的魔法是如何工作的一样,事实上,像IL Spy和Redgate的.NET Reflector这样的工具就是这样做的——使用反射。只是永远不要在代码中隐藏任何秘密,比如加密/解密密钥:)如果不编写构造函数,C#会自动添加一个默认的构造函数,例如Public WidgetBlue(){}@Kevin它不会