开发者

Generic method with generic type problem

I have problem with constraints on generic method. Here is code for all classes:

namespace Sdk.BusinessObjects
{
    public interface IBusinessObject
    {
    }
}

namespace Sdk.BusinessObjects
{
    [DataContract]
    public class AccountDetails : IBusinessObject
    {
        [DataMember]
        public virtual Guid AccountId { get; set; }

    // More properties...
    }
}

namespace Sdk.BusinessLogic
{
    public interface IManager<T> where T : IBusinessObject
    {
        T Add(T businessObject);
        void Delete(T businessObject);
        IList<T> ListAll();
    }
}

namespace Sdk.BusinessLogic
{
    public interface IAccountManager : IManager<AccountDetails>
    {
        void ChangeAccountState(Guid accountId, string state);
    }
}

namespace Sdk.BusinessLogic
{
    public interface IManagerFactory
    {
        T Create<T>() where T : IManager<IBusinessObject>;
    }

    public class ManagerFactory : IManagerFactory
    {
        public T Create<T>() where T : IManager<IBusinessObject>
        {
            // resolve with Unity and return
        }
    }
}

So, I have main IBusinessObject interface for all business objects (like AccountDetails) and IManager as generic manager interface for business objects. I wanted to create factory for these managers with constraints. When I try something like this in UnitTest:

IManagerFactor开发者_开发问答y factory = new ManagerFactory();
factory.Create<IAccountManager>();

I get error: The type 'Sdk.BusinessLogic.IAccountManager' cannot be used as type parameter 'T' in the generic type or method 'Sdk.BusinessLogic.IManagerFactory.Create()'. There is no implicit reference conversion from 'Sdk.BusinessLogic.IAccountManager' to 'Sdk.BusinessLogic.IManager'.

How can this be done?


Basically your problem is that IManager<T> is invariant, and has to be as you've got values coming out of the API and values going into it. So an IAccountManager isn't an IManager<IBusinessObject>, because otherwise you could write:

IAccountManager m1 = new SomeImplementation();
IManager<IBusinessObject> m2 = m1;
m2.Add(new SomeArbitraryBusinessObject());

An account manager is only meant to manage accounts, not just any business object.

One option is to use two generic type parameters instead of one for ManagerFactory.Create:

public TManager Create<TManager,TObjectType>()
    where TManager : IManager<TObjectType>
    where TObjectType : IBusinessObject
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜