Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 限制类工厂设计模式_C#_Friend_Class Factory - Fatal编程技术网

C# 限制类工厂设计模式

C# 限制类工厂设计模式,c#,friend,class-factory,C#,Friend,Class Factory,在C语言中,有没有一种优雅的或任何方式来实现以下目标 让我们有一个可进一步派生到Item1、Item2…的类ItemBase,它不允许直接实例化非公共构造,以防止用户创建Item*的任何“未跟踪”实例。 让我们有一个非静态类管理器,它的实例只允许有多个实例才能创建和提供Item*的实例,因为它们跟踪生成的实例并做一些额外的工作。 让我们有一个可选的要求:Manager实例希望操纵托管项实例的非公共成员,就像Manager是Item*的朋友一样。 如果经理不被迫成为项目*的派生人,那就太好了。 如

在C语言中,有没有一种优雅的或任何方式来实现以下目标

让我们有一个可进一步派生到Item1、Item2…的类ItemBase,它不允许直接实例化非公共构造,以防止用户创建Item*的任何“未跟踪”实例。 让我们有一个非静态类管理器,它的实例只允许有多个实例才能创建和提供Item*的实例,因为它们跟踪生成的实例并做一些额外的工作。 让我们有一个可选的要求:Manager实例希望操纵托管项实例的非公共成员,就像Manager是Item*的朋友一样。 如果经理不被迫成为项目*的派生人,那就太好了。 如果有尽可能少的反射就好了。 注:

如果可能的话,请考虑这是一个从思考过程中提出的问题,如何以一种最好和优雅的方式实施特定的问题解决方案。我希望它是一般的,不,我没有来源,是的,我已经尝试了一些变种,但没有一个满足我的需要。多谢各位

据我所知,没有可接受的朋友替代方案任何内部和内部可视属性似乎都是好的,因此ItemBase只提供了“特殊”但公开的修改方法,用户必须知道,这些方法不适合他:o

我喜欢,但我无法发明如何允许多个管理器实例使用它


我想这也许能回答你的问题:

public class ItemBase

{
    protected ItemBase()
    {

    }
    public void PublicMethod() { }
    public int PublicProperty { get; set; }
}

public class Factory
{
    private class PrivateItemBase : ItemBase
    {
        public void PrivateMethod() { }
        public int PrivateProperty { get; set; }
    }

    public Factory(int id)
    {

    }

    public IEnumerable<ItemBase> Items { get; private set; }
    public ItemBase CreateItem()
    {
        PrivateItemBase rValue = new PrivateItemBase();

        rValue.PrivateMethod();
        rValue.PrivateProperty = 4;

        return rValue;
    }
}

好吧,放弃。如果这可能有助于充分理解其目的,那么我目前找到了一个不那么糟糕的解决方案。传递创建函数是通过用户无法访问的静态构造函数完成的,不幸的是,丑陋的事情是它们的调用

有没有办法让它变得更好

项目定义:

namespace SpecialFactory
{
    public enum ItemType
    {
        Item1,
        Item2,
        // ... Anyone deriving the Item* should add an item here
    }

    public abstract class ItemBase
    {
        public abstract ItemType Id {get;}

        public static void RegisterAllCreators()
        {
            // Force static constructors invocation
            var it = Item1.ClassId | Item2.ClassId; // Anyone deriving the Item* should ensure invocation of Manager.RegisterCreator
        }
    }

    public class Item1 : ItemBase
    {
        static Item1()
        {
            Manager.RegisterCreator(ItemType.Item1, () => new Item1());
        }

        protected Item1()
        {
        }

        public static   ItemType ClassId => ItemType.Item1;
        public override ItemType Id      => ClassId;
    }

    public class Item2 : ItemBase
    {
        static Item2()
        {
            Manager.RegisterCreator(ItemType.Item2, () => new Item2());
        }

        protected Item2()
        {
        }

        public static   ItemType ClassId => ItemType.Item2;
        public override ItemType Id      => ClassId;
    }
}
经理:

namespace SpecialFactory
{
    public class Manager
    {
        static Manager()
        {
            ItemBase.RegisterAllCreators();
        }

        protected static Dictionary<ItemType, Func<ItemBase>> creators = new Dictionary<ItemType, Func<ItemBase>>();
        protected readonly List<ItemBase> managedItems = new List<ItemBase>();

        protected ItemBase CreateItem(ItemType type)
        {
            ItemBase item = null;

            if (creators.ContainsKey(type))
            {
                if ((item = creators[type]()) != null)
                    managedItems.Add(item);
            }

            return item;    
        }

        public static void RegisterCreator(ItemType type, Func<ItemBase> creator)
        {
            if (!creators.ContainsKey(type))
                creators[type] = creator;
        }

        public Manager()
        {

        }

        public ItemBase Test(ItemType type)
        {
            // var notAllowed = new Item1();
            var allowed = CreateItem(type);

            return allowed;
        }
    }
}

使用内部命令有什么问题?用户是否将直接使用您的源代码,而不是将您的库用作引用的DLL?是的,让用户+=另一个程序员使用codeConsider定义多个接口、一个IItemBase、IItem1、,IItem2包含要使用的公共API,以及包含内部/私有操作方法的IInternalItem。您的工厂/API/使用通常应与IItem1接口绑定;也就是说,用户不处理Item1类。您的Manager类可以处理Item1类或IInternalItem接口,并使用私有操作方法;他们必须有目的地强制转换到Item1类或IInternalItem来访问隐藏的方法。编辑:我忘了提一下,你也可以考虑使用它。把iTeBasic当作抽象类来考虑。它可能由另一个类派生,比如公共类Item1:itembease{…};甚至更多:公共类Item1Better:Item1{…};。工厂通过枚举值或类型类获取有关要创建的类型的信息。
namespace SpecialFactory
{
    class Program
    {
        static void Main(string[] args)
        {
            var m1 = new Manager();
            var m2 = new Manager();

            var i1 = m1.Test(ItemType.Item1);
            var i2 = m2.Test(ItemType.Item2);
        }
    }
}