2015-03-23 2 views
2

У меня есть интерфейсАбстрактные классы 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)); 
     } 

Как я могу Асесс атрибуты в моем шоколадном торте, чтобы использовать их как

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); 
+1

"Право" способ сделать это 'AbstractCake' должен иметь' IsPacked', 'IsDecorated' и' NameOfCake' определяется как абстрактные свойства/методы в нем. –

ответ

5

Проблема здесь в том, что AbstractFactory есть метод, который возвращает AbstractCake и AbstractCake сам не имеет никаких свойств вообще. Как она стоит, вам нужно будет обратным приведение в торте (прямой или с as ключевым словом) к ChocolateCake до доступа к любому из его свойств, что является очень неаккуратно:

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

Вот некоторые соображения:

  1. Переместить свойства, общие для всех типов торта, в AbstractCake, например NameOfCake, IsPacked и IsDecorated
  2. Учитывая, что AbstractFactory и AbstractCake классы не имеют реализации на всех, рассмотреть вопрос об изменении этих интерфейсов вместо абстрактных классов, то есть ICakeFactory и ICake. Бетонные реализации будут ChocolateCakeFactory и ChocolateCake по-прежнему.
  3. Потребители завода и торт должно теперь только получить доступ к тому, что выставлено на интерфейсах (ICakeFactory, ICake и IBox), и не нужно делать какие-либо вниз литье или делать какие-либо предположения о фактическом конкретном типе торта и т.д.

ie

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

Re: Использование

Это очень маловероятно, что вы когда-нибудь будет это делать:

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

Edit, Re Raise изменении событий

Это предполагает реализацию 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); 
+0

Спасибо большое !!!! И еще один вопрос, хочу ли я подписаться на событие, что свойства были изменены, как это сделать? –

+0

Я обновил, хотя, я думаю, технически это новый вопрос (будет трудно найти других). Skype - извините, нет, у меня есть дневная работа :) - просто продолжайте задавать хорошие вопросы, как тот, который вы здесь задали, а другие помогут. – StuartLC

0

Будет ли эта работа?

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

... 

var cake = str.GetFactory().CreateCake<ChocolateCake>(); 
Смежные вопросы