我有一个看起来像这样的课程
public class TableMapper<TSource>
{
....
....
public TableMapper(IQueryExtractor queryExtractor, string tableAliasPrefix = null)
{
QueryExtractor = queryExtractor;
TableAliasPrefix = tableAliasPrefix;
}
....
....
}
我从另一个类中创建了这个类的实例,如此
public class CustomerMapper : ReportTemplate
{
private readonly IQueryExtractor QueryExtractor;
private readonly TableMapper<Customer> customerMapper;
private readonly TableMapper<Client> clientMapper;
public CustomerMapper(DbContext context)
: base(new QueryBuilder(), new QueryExecutor(context.Database.Connection.ConnectionString))
{
QueryExtractor = new QueryExtractor(context);
customerMapper = new TableMapper<Customer>(QueryExtractor, "Customer");
clientMapper = new TableMapper<Client>(QueryExtractor);
}
public List<IReportRelation> ReportRelations
{
return new List<IReportRelation>
{
new ReportRelation
{
ForeignColumn = customerMapper.GetReportColumn(x => x.ClientId),
LocalColumn = clientMapper.GetReportColumn(x => x.Id),
},
};
}
}
正如您在ReportRelations
方法中看到的,我返回ReportRelation
实现列表。我需要做的是在我的IReportRelation
界面和ReportRelation
实现中再添加2个公共属性来保存我TableMapper<TSource>
类的实例
如何在IReportRelation
接口中定义一个具有customerMapper
属性的副本/实例的公共变量?
以下是我的IReportRelation
定义
public interface IReportRelation
{
//Here I need to add an instance that hold the localTable
//something like this TableMapper<TSource> LocalMapper
//something like this TableMapper<TSource> ForeignMapper
IReportColumn ForeignColumn { get; set; }
IReportColumn LocalColumn { get; set; }
}
已更新
在Tim的建议下面我将我的代码更改为以下
public interface IReportRelation<TLocal, TForeign>
{
TableMapper<TLocal> LocalMapper { get; set;}
TableMapper<TForeign> ForeignMapper { get; set; }
IReportColumn ForeignColumn { get; set; }
IReportColumn LocalColumn { get; set; }
}
然后在我的CustomerMapper
课程中,我的功能将如下所示
public List<IReportRelation<Customer,Client> ReportRelations
{
return new List<IReportRelation<Customer,Client>>
{
new ReportRelation<Customer,Client>
{
LocalMapper = this.customerMapper,
ForeignMapper = this.clientMapper,
ForeignColumn = customerMapper.GetReportColumn(x => x.ClientId),
LocalColumn = clientMapper.GetReportColumn(x => x.Id),
},
};
}
但问题是ReportRelations
将始终返回IReportRelation<Customer,Client>
列表。如果我想返回类似这样的混合列表,例如
public List<IReportRelation<Customer,Client> ReportRelations
{
return new List<IReportRelation<Customer,Client>>
{
new ReportRelation<Customer,Client>
{
LocalMapper = this.customerMapper,
ForeignMapper = this.clientMapper,
ForeignColumn = customerMapper.GetReportColumn(x => x.ClientId),
LocalColumn = clientMapper.GetReportColumn(x => x.Id),
},
new ReportRelation<Customer,Team>
{
LocalMapper = this.customerMapper,
ForeignMapper = this.teamMapper,
ForeignColumn = customerMapper.GetReportColumn(x => x.TeamId),
LocalColumn = clientMapper.GetReportColumn(x => x.Id),
},
};
}
答案 0 :(得分:2)
您不能在列表中混合使用不同的泛型类型参数。这个问题的一个常见解决方案是拥有一个非通用的基本接口,并从中派生出通用接口。
public interface ITableMapper
{
// Use Sytem.Type arguments where appropriate and
// the object type instead of generic types
...
}
public class TableMapper<TSource> : ITableMapper
{
...
}
public interface IReportRelation
{
ITableMapper LocalMapper { get; }
ITableMapper ForeignMapper { get; }
IReportColumn ForeignColumn { get; set; }
IReportColumn LocalColumn { get; set; }
}
public interface IReportRelation<TLocal, TForeign> : IReportRelation
{
new TableMapper<TLocal> LocalMapper { get; set; }
new TableMapper<TForeign> ForeignMapper { get; set; }
}
public class ReportRelation<TLocal, TForeign> : IReportRelation<TLocal, TForeign>
{
ITableMapper IReportRelation.LocalMapper { get { return LocalMapper; } }
ITableMapper IReportRelation.ForeignMapper { get { return ForeignMapper; } }
public TableMapper<TLocal> LocalMapper { get; set; }
public TableMapper<TForeign> ForeignMapper { get; set; }
public IReportColumn ForeignColumn { get; set; }
public IReportColumn LocalColumn { get; set; }
}
确保明确实现非通用接口。当直接与班级合作时,这会隐藏它。
现在您可以拥有List<IReportRelation>
并填写具有不同泛型类型参数的ReportRelation<TLocal, TForeign>
个对象。
您可以在.NET Framework Libary中找到此模式。请参阅IList<T> : IList
,IEnumerable<T> : IEnumerable
,依此类推......
答案 1 :(得分:0)
我认为Client
和Customer
可能会发生变化。在这里你可以做什么:
public interface IReportRelation<TLocal, TForeign>
{
TableMapper<TLocal> LocalMapper { get; set; }
TableMapper<TForeign> ForeignMapper { get; set; }
IReportColumn ForeignColumn { get; set; }
IReportColumn LocalColumn { get; set; }
}
public class ReportRelation<TLocal, TForeign> : IReportRelation<TLocal, TForeign>
{
public TableMapper<TLocal> LocalMapper { get; set; }
public TableMapper<TForeign> ForeignMapper { get; set; }
public IReportColumn ForeignColumn { get; set; }
public IReportColumn LocalColumn { get; set; }
}
适用于您的CustomMapper
班级
public class CustomerMapper : ReportTemplate
{
...
public List<IReportRelation<Customer, Client>> ReportRelations
{
return new List<IReportRelation<Customer, Client>>
{
new ReportRelation<Customer, Client>
{
LocalMapper = this.customerMapper,
ForeignMapper = this.clientMapper,
ForeignColumn = customerMapper.GetReportColumn(x => x.ClientId),
LocalColumn = clientMapper.GetReportColumn(x => x.Id)
}
};
}
}