1

假设我有两个接口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非派生类名。

我想知道它是否是好的实现或非通用版本应该有与我到目前为止所做的相反的通用实例?

   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 中可用的放置属性应该在每个派生类上都可用,并且还需要保留受保护的方法和属性

4

1 回答 1

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,因为所有类型都已经有了这些。

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

此外,这与泛型与非泛型或提到的所有其他内容无关。

于 2012-10-13T12:20:21.870 回答