抽象类C#

时间:2015-03-23 04:26:31

标签: c#

我有一个界面

using ClassAbstractFactory;
public interface IPlugin
{
    AbstractFactory GetFactory();  
}

和AbstractFactory

public abstract class AbstractFactory
{
    public abstract AbstractCake CreateCake();
    public abstract AbstractBox CreateBox();
}

public abstract class AbstractCake
{

    public abstract void Interact(AbstractBox box);

}

public abstract class AbstractBox
{

}

我的.dll继承了AbstractCake

 public class ChocolateCake : AbstractCake
{

    private bool _isPacked;
    private bool _isDecorated;
    private string _nameOfCake;

    public ChocolateCake()
    {
        _isPacked = false;
        _isDecorated = false;
        _nameOfCake = "Шоколадный";
    }


   public bool IsPacked
   {
        get { return _isPacked; }
   }

    public bool IsDecorated
    {
        get { return _isDecorated; }

    }

    public string NameOfCake { get; set; }


    public override void Interact(AbstractBox box)
    {     
            _isPacked = true;       
    }


}

我像这样加载dll:

 public IPlugin LoadAssembly(string assemblyPath)
    {
        Assembly ptrAssembly = Assembly.LoadFile(assemblyPath);

        foreach (Type item in ptrAssembly.GetTypes())
        {
            if (!item.IsClass) continue;
            if (item.GetInterfaces().Contains(typeof(IPlugin)))
            {
                return (IPlugin)Activator.CreateInstance(item);
            }
        }
        throw new Exception("Invalid DLL, Interface not found!");
    }

        List<IPlugin> list = new List<IPlugin>();
        foreach (var assemblyPath in GetPathsListToDll())
        {
            list.Add(LoadAssembly(assemblyPath));
        }

如何使用我的ChocolateCake中的属性,使用它们

foreach (var str in list)
        {
            Boolean a = str.GetFactory().GetCake().CreateCake().IsPacked;
        }

或者像这样

string a = str.GetFactory().GetCake().CreateCake().NameOfCake;

或者像这样

str.GetFactory().GetCake().CreateCake().NameOfCake("Something");

或者像这样

str.GetFactory().GetCake().CreateCake().IsDecorated(true);

2 个答案:

答案 0 :(得分:5)

这里的问题是AbstractFactory有一个返回AbstractCake的方法,而AbstractCake本身根本没有属性。就目前而言,您需要在访问任何属性之前将Cake(直接或as关键字)向下转换为ChocolateCake,这非常麻烦:

string a = (ChocolateCake)(str.GetFactory().CreateCake()).NameOfCake;

以下是一些注意事项:

  1. 将所有类型的蛋糕所共有的属性移动到AbstractCake,例如NameOfCakeIsPackedIsDecorated
  2. 鉴于AbstractFactoryAbstractCake类根本没有任何实现,请考虑将这些更改为接口而不是抽象类,即ICakeFactoryICake。具体实现将像以前一样ChocolateCakeFactoryChocolateCake
  3. 工厂和蛋糕的消费者现在应该只访问接口(ICakeFactoryICakeIBox)上显示的内容,而不需要进行任何向下转换或制作关于蛋糕的实际具体类型的任何假设等。
  4. public interface ICake
    {
        void Interact(IBox box);
        bool IsPacked { get; }
        bool IsDecorated { get; }
        string NameOfCake { get; set; }
    }
    
    public class ChocolateCake : ICake
    {
        private bool _isPacked;
        private bool _isDecorated;
        private string _nameOfCake;
    
        public ChocolateCake() // ctor is not on the interface and is implementation detail
        {
            _isPacked = false;
            _isDecorated = false;
            _nameOfCake = "Шоколадный";
        }       
    
        public void Interact(IBox box) {...}
        public bool IsPacked { get { return _isPacked; } }
        public bool IsDecorated { get { return _isDecorated; } }
        // ...
    }
    
    public interface ICakeFactory
    {
        ICake CreateCake();
        IBox CreateBox();
    }
    
    public class ChocolateCakeFactory : ICakeFactory
    {
        public ICake CreateCake()   {return new ChocolateCake();}
        public IBox CreateBox() {return new ChocolateCakeBox();} 
    }
    

    重新:用法

    你不太可能这样做:

    string a = str.GetFactory().GetCake().CreateCake().NameOfCake;
    str.GetFactory().GetCake().CreateCake().NameOfCake = "Something"; // Prop setter
    

    因为这会每次创建一个新的蛋糕实例(并丢弃实例)。怎么样:

    class Bakery
    {
       private readonly ICakeFactory _cakeFactory;
       public Bakery(ICakeFactory cakeFactory)
       {
           Contract.Requires(cakeFactory != null);
           cakeFactory = _cakeFactory;
       }
    
       bool BakeStuff()
       {
           var cake = _cakeFactory.CreateCake();
           cake.NameOfCake = "StackOverflow";
           return cake.IsDecorated && cake.IsPacked;
       }
    }
    

    编辑,重新提升更改事件

    这涉及实施INotifyPropertyChanged

    public interface ICake : INotifyPropertyChanged
    

    然后你可以提高你的可变属性,例如

    public string NameOfCake
    {
        get { return _nameOfCake} ;
        set { 
            var propChanged = PropertyChanged;
            if (propChanged != null && value != _nameOfCake)
            {
                propChanged(this, new PropertyChangedEventArgs("NameOfCake"));
            }
            _nameOfCake = value;
        }
    }
    

    订阅如此

    var cake = new ChocolateCake();
    cake.PropertyChanged += (sender, eventArgs) 
         => Console.WriteLine("Property {0} has changed", eventArgs.PropertyName);
    

答案 1 :(得分:0)

这会有用吗?

public abstract class AbstractFactory
{
    public abstract TCake CreateCake<TCake>() where TCake : AbstractCake, new();
    public abstract AbstractBox CreateBox();
}

...

var cake = str.GetFactory().CreateCake<ChocolateCake>();