ISomeInterface
とISomeInterface<T>
からISomeInterface<T>
継承する2 つのインターフェイスがあるとし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 で利用可能な put プロパティは、すべての派生クラスで利用可能である必要があり、保護されたメソッドとプロパティも保持する必要があります