假设我有两个接口ISomeInterface
,ISomeInterface<T>
并且ISomeInterface<T>
继承自ISomeInterface
.
现在如果我们必须类Someclass
,SomeClass<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
非派生类名。
我想知道它是否是好的实现或非通用版本应该有与我到目前为止所做的相反的通用实例?
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 中可用的放置属性应该在每个派生类上都可用,并且还需要保留受保护的方法和属性