继承与泛型的组合

时间:2012-10-13 12:07:19

标签: c# design-patterns generics composition

假设我有两个接口ISomeInterfaceISomeInterface<T>ISomeInterface<T>继承自ISomeInterface

现在,如果我们必须使用类SomeclassSomeClass<T>,我们如何实现组合而不是继承?哪个类应该有另一个类的实例?

public interface ISomeInterface
{
     string Name {get;}
}

public interface ISomeInterface<T> : ISomeInterface
{
     string ResultMessage{get;}
}

public class SomeClass : ISomeInterface
{
     public string Name
     {
          get{return this.GetType().Name;
     }
}
public class SomeClass<T> ISomeInterface<T>
{
     ISomeInterface _someclassinstance = new SomeClass;

     public string Name
     {
          get{return _someclassInstance.Name;
     }

     public string Caption
     {
          get{return "Demo Caption";}
     }
}

当我在类的泛型版本的实例上调用Name属性时,它将返回SomeInterface而不是派生类名。

我想知道它是好的实现还是Non-Generic版本应该具有与我迄今为止所做的相反的Generic实例?

   public abstract class ViewModelBase : NotificationObject, IViewModel
{
    private IViewModel _parent;
    private string _title;
    private bool _isBusy;
    private bool _isDitry;

    #region Viewmodel Initialization steps

    /// <summary>
    /// Initializes a new instance of the <see cref="ViewModelBase"/> class.
    /// </summary>
    internal protected ViewModelBase()
    {
        ResolveDependencies();

        Load();
    }

    /// <summary>
    /// Exposes a way for external users to pass a boxed payload
    /// to this view model for initialization purposes.
    /// Inheritors can override this method to perform specific
    /// initialization and validation operations depending on the
    /// payload sent from the outside.
    /// </summary>
    /// <param name="payload">
    /// Represents the boxed payload the view model uses
    /// for initialization purposes.
    /// </param>
    public virtual void Initialize(object payload)
    {
    }

    /// <summary>
    /// Loads the view model.
    /// </summary>
    private void Load()
    {
        BeforeLoad();
        OnLoad();
    }

    /// <summary>
    /// Gives inheritors the opportunity to perform an operation before the view model loads.
    /// </summary>
    protected virtual void BeforeLoad()
    {
    }

    /// <summary>
    /// Gives inheritors the opportunity to perform specific operations when the view model loads for the first time.
    /// </summary>
    protected virtual void OnLoad()
    {
        SetupEvents();
    }

    /// <summary>
    /// Registers listeners for all events in which the ViewModel is interested in.
    /// </summary>
    protected virtual void SetupEvents()
    {

    }

    /// <summary>
    /// Resolves the dependencies for this view model.
    /// </summary>
    private void ResolveDependencies()
    {
        BeforeResolveDependencies();
        EventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
        OnResolveDependencies();
    }

    /// <summary>
    /// Gives inheritors the opportunity to perform an operation before the dependencies are resolved.
    /// </summary>
    protected virtual void BeforeResolveDependencies()
    {
    }

    /// <summary>
    /// Gives inheritors the opportunity to resolve dependencies of their own.
    /// </summary>
    protected virtual void OnResolveDependencies()
    {
    }

    /// <summary>
    /// Event handler that notifies the new children of the parent
    /// view model they live in and removes the parent when they are
    /// removed from the collection.
    /// </summary>
    /// <param name="sender">Child view model rising the event.</param>
    /// <param name="e">Changes made to the collection.</param>
    protected void ChildCollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach (var item in e.NewItems)
            {
                ((ViewModelBase)item).Parent = this;
            }
        }

        if (e.OldItems == null) return;
        foreach (var item in e.OldItems)
        {
            ((ViewModelBase)item).Parent = null;
        }
    }

    #endregion

    #region Members of IViewModel

    /// <summary>
    /// Gets the title.
    /// </summary>
    public string Title
    {
        get { return _title ?? (_title = GetType().Name); }
        protected set
        {
            _title = value;
            RaisePropertyChanged(() => Title);
        }
    }

    /// <summary>
    /// Gets or sets a value indicating whether the ViewModel is busy.
    /// </summary>
    /// <value><see langword="true"/> if the ViewModel is busy; otherwise, <see langword="false"/>.</value>
    public bool IsBusy
    {
        get { return _isBusy; }
        protected set
        {
            _isBusy = value;
            RaisePropertyChanged(() => IsBusy);
        }
    }

    /// <summary>
    /// Gets or sets a value indicating whether this instance is dirty.
    /// </summary>
    /// <value>
    ///   <c>true</c> if this instance is dirty; otherwise, <c>false</c>.
    /// </value>
    public bool IsDirty
    {
        get { return _isDitry; }
        set
        {
            _isBusy = value;
            RaisePropertyChanged(() => IsDirty);
        }
    }

    /// <summary>
    /// Gets or sets the view for which this instance is set as DataContext.
    /// </summary>
    /// <value>
    /// The view.
    /// </value>
    public IView View { get; set; }

    /// <summary>
    /// Gets the parent ViewModel holding this instance as
    /// childe ViewModel collection item.
    /// </summary>
    public IViewModel Parent
    {
        get { return _parent; }
        set
        {
            _parent = value;
            RaisePropertyChanged(() => Parent);
        }
    }

    #endregion

    /// <summary>
    /// Get CurrentInstance of EventAggregator
    /// </summary>
    private IEventAggregator EventAggregator { get; set; }

    /// <summary>
    /// Gets the dispatcher.  Works at run-time and test-time.
    /// </summary>
    /// <value>The dispatcher.</value>
    protected static Dispatcher Dispatcher
    {
        get { return Application.Current != null ? Application.Current.Dispatcher : Dispatcher.CurrentDispatcher; }
    }


    /// <summary>
    /// Resolves this instance for specific type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    protected static T Resolve<T>()
    {
        try
        {
            return ServiceLocator.Current.GetInstance<T>();
        }
        catch (Exception)
        {
            return default(T);
        }
    }

    /// <summary>
    /// Resolves all instances of specific type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    protected static IEnumerable<T> ResolveAll<T>()
    {
        return ServiceLocator.Current.GetAllInstances<T>();
    }

    /// <summary>
    /// Registers for specific event inside system event providing some filter parameters.
    /// </summary>
    /// <typeparam name="TEvent">The type of the event.</typeparam>
    /// <param name="onEvent">The on event.</param>
    /// <param name="filter">The filter.</param>
    protected void RegisterForEvent<TEvent>(Action<TEvent> onEvent, Predicate<TEvent> filter = null) where TEvent : class
    {
        EventAggregator.Subscribe<TEvent>(onEvent, ThreadOption.PublisherThread, false, filter);
    }

    /// <summary>
    /// Broadcasts the specified event object.
    /// </summary>
    /// <typeparam name="TEvent">The type of the event.</typeparam>
    /// <param name="eventObject">The event object.</param>
    protected void Broadcast<TEvent>(TEvent eventObject) where TEvent : class
    {
        EventAggregator.Publish(eventObject);
    }
}

这是IViewModel基类和

的完整实现
    public abstract class ViewModelBase<TValidator> : ViewModelBase,IViewModel<TValidator>, IDataErrorInfo
    where TValidator : IValidator, new()
{
    private bool _islValid;
    readonly IValidator _validator = new TValidator();

    /// <summary>
    /// Get Validation processor for ViewmodelInstance 
    /// </summary>
    /// <value>
    /// The Validator.
    /// </value>
    public TValidator Validator
    {
        get { return (TValidator) _validator; }
    }

    public bool IsValid
    {
        get
        {
            _islValid = SelfValidate().IsValid;
            return _islValid;
        }
        private set
        {
            _islValid = value;                
            RaisePropertyChanged(() => IsValid);
        }
    }
// Implementation for validation
}

这里我发布了这两个类的源代码。并且有N个不同的接口和类,它们都需要从这些类的通用版本或非通用版本派生。 IViewmodel中的put属性应该在每个派生类上都可用,并且需要保留受保护的方法和属性

1 个答案:

答案 0 :(得分:1)

关于组合,通用版本需要使用非通用版本。

你不能采用相反的方式,因为类的通用版本是强类型的,这意味着它包含比非泛型版本更多的编译时细节。没有办法将所需类型从非泛型类传递给内部泛型类。

Name属性开始,它实际上完成了它应该做的事情,返回Name类型的SomeClass

修改

如果您需要一种始终返回当前类型名称的方法,那么有很多方法可以解决这个问题。您可以为此创建普通或通用帮助方法,或者例如,您可以为ISomeInterface类型创建扩展方法,并使用它而不是Name属性:

public static class SomeInterfaceExtensions
{
    // Extension
    public static string GetName(this ISomeInterface some)
    {
        return some.GetType().Name;
    }
}

// Usage
var some = new SomeClass<int>();
var name = some.GetName();

但你所要达到的只是制作GetType().Name的快捷方式,因为所有类型都有。{/ p>

我在这个解决方案中看不到多少价值,至少在给定的类型名称示例中是这样。

此外,这与仿制药与非仿制药或所有其他提及的东西无关。