如何实现多个子对象.net的继承

时间:2014-12-03 10:38:24

标签: c# asp.net .net inheritance

假设我有一个名为BaseService的基类,那么我有另一个名为AuditService的类,它继承自BaseService,也许还有另一个名为FooService的类,它也继承自BaseService。

所以层次结构看起来像这样

BaseService
|
---- AuditService
|
---- FooService

现在如果我需要一个包含AuditService和FooService的所有功能的新服务呢?

c#不允许你从多个对象继承,所以我该怎么做呢?

我不想继承1项服务,并重新编码其余所有项目。

编辑:

要包含有关我的课程的更多详细信息,请参阅下面的代码。

正如您所看到的,我在foo服务和可审计服务中覆盖了基本服务的特定功能。将来我需要一个服务来实现baseservice,foo服务和可审计服务的所有功能。

BASESERVICE

public abstract class BaseService<TEntity> 
    where TEntity : class, IBaseEntity
{
    protected DataContext _context;

    protected BaseService(DataContext context)
    {
        _context = context;
    }

    public virtual async Task<ICollection<TEntity>> GetAllAsync()
    {
        return await _context.Set<TEntity>().ToListAsync();
    }

    public virtual Task<TEntity> GetAsync(long id)
    {
        return _context.Set<TEntity>().FindAsync(id);
    }

    public virtual Task<int> AddAsync(TEntity t)
    {
        if (_context.Entry(t).State == EntityState.Detached)
        {
            _context.Set<TEntity>().Add(t);
        }

        _context.Entry(t).State = EntityState.Added;

        return _context.SaveChangesAsync();
    }

    public virtual Task<int> AddAllAsync(ICollection<TEntity> all)
    {
        foreach (var item in all)
        {
            if (_context.Entry(item).State == EntityState.Detached)
            {
                _context.Set<TEntity>().Add(item);
            }

            _context.Entry(item).State = EntityState.Added;
        }

        return _context.SaveChangesAsync();
    }

    public virtual Task<int> UpdateAsync(TEntity updated)
    {
        _context.Entry(updated).State = EntityState.Modified;

        return _context.SaveChangesAsync();
    }

    public virtual async Task<int> DeleteAsync(long key)
    {
        TEntity entity = await GetAsync(key);

        _context.Entry(entity).State = EntityState.Deleted;

        return await _context.SaveChangesAsync();
    }

    public virtual Task<int> DeleteAsync(TEntity t)
    {
        _context.Entry(t).State = EntityState.Deleted;

        return _context.SaveChangesAsync();
    }

}

AUDITABLESERVICE

public class AuditableService<TEntity> : BaseService<TEntity>
    where TEntity : class, IAuditableEntity
{

    public virtual override Task<int> DeleteAsync(long key)
    {
        return DeleteAsync(key, true);
    }

    public virtual async Task<int> DeleteAsync(long key, bool useFlag)
    {
        TEntity entity = await GetAsync(key);

        return await DeleteAsync(entity, useFlag);
    }

    public virtual override Task<int> DeleteAsync(TEntity t)
    {
        return DeleteAsync(t, true);
    }

    public virtual Task<int> DeleteAsync(TEntity t, bool useFlag)
    {
        if (useFlag)
        {
            // flag item as deleted
            t.IsDeleted = true;

            return UpdateAsync(t);
        }
        else
        {
            return base.DeleteAsync(t);
        }
    }
}

FooService接口

public class FooService<TEntity> : BaseService<TEntity>
    where TEntity : class, IBaseEntity
{
    protected IValidator<TEntity> _validator;

    protected ValidatorService(DataContext context)
        : base(context)
    {

    }

    public override async Task<int> AddAsync(TEntity t)
    {
        var results = await _validator.ValidateAsync(t);

        if (results.IsValid)
        {
            return await base.AddAsync(t);
        }
        else
        {
            throw new ValidationException(results.Errors);
        }
    }

    public override async Task<int> UpdateAsync(TEntity updated)
    {
        var results = await _validator.ValidateAsync(updated);

        if (results.IsValid)
        {
            return await base.UpdateAsync(updated);
        }
        else
        {
            throw new ValidationException(results.Errors);
        }
    }

}

2 个答案:

答案 0 :(得分:2)

正如@Christos所说,.net中没有多重干预支持 - 您必须描述您的意图,以获得符合您需求的解决方案。

组合物可以是解决方案,例如创建另一个派生自BaseService的类,该类保存对AutidService的引用和FooService实例,以便将操作委托给它们(如果BaseService已经为您的新服务提供了良好的接口,那么这将是一个解决方案。可能的好处是,您可以控制委派就像装饰模式一样,这可能是遵循SRP(单一责任原则)的干净灵魂。)

向我们提供有关新服务如何重新使用已定义服务的更多信息......

由于BaseService定义了您的具体服务提供的所有方法,因此您添加的代码非常适合于合成:

public class NewService<T> : BaseService<T>
{
    private readonly FooService<T> _fooService;
    private readonly AuditableService<T> _auditableService;
    public NewService (AuditableService<T> auditableService, FooService<T> fooService)
    {
        if(auditableService  == null)
            throw new ArgumentNullException("auditableService ");

        if(fooService == null)
            throw new ArgumentNullException("fooService");

        _auditableService = auditableService;
        _fooService = fooService;
    }

    public override Task<int> AddAsync(T t)
    {
         return _fooService.UpdateAsync(t);
    }

    public override Task<int> DeleteAsync(T t)
    {
         return _auditableService.DeleteAsync(t);
    }
}

编辑UnitTesting 您可以模拟传递的服务(因为它们具有共同的抽象基类)并验证它们是否由您的新服务调用。这比单元测试更多的交互测试,但它将确保您调用正确的方法。如果新服务中没有预处理/后处理,则您不需要对新服务进行任何进一步测试。

答案 1 :(得分:1)

使用类.net不支持多重继承。您只能从一个类继承,但可以根据需要实现任意数量的接口。因此,可用于实现多重继承的机制是使用实现多个接口。

以下内容很简单:

public class AuditService : BaseService
{ }

public class FooService : BaseService
{ }

现在,如果您想要AuditServiceFooService所拥有的所有服务类,您可以声明一个接口,例如: IUnionInterface,其中包含您想要的所有内容,然后您可以从您的班级中提出IUnionInterface

public class SuperService : IUnionInterface
{ }

或者您可以声明包含AuditServiceFooServiceINonCommonFeatures的非常见功能的界面,然后让您的类继承自BaseService并实现{{ 1}}。

INonCommonFeatures

现在您只需要实现public class SuperService : BaseService, INonCommonFeatures { }

的功能