我有以下类结构
public abstract class SalesTransaction
{
}
public class Invoice : SalesTransaction
{
}
public class Estimate : SalesTransaction
{
}
public interface IRepostory<T>
{
T First(Expression<Func<T, bool>> predicate);
void Add(T item);
T Single(Expression<Func<T, bool>> predicate, bool disableTracking = false);
}
我可以通过将其IRepository<Invoice>
投射到IRepository<Estimate>
而以某种方式抽象IRepository<SalesTransaction>
和IRepository<Invoice> invoiceRepository = /* Create instance */;
IRepository<SalesTransaction> salesTransaction = invoiceRepository;
吗?
<?php
if (is_dir('dir')) {
if ($dh = opendir('dir')) {
while (($file = readdir($dh)) !== false) {
echo "filename:".$file."<br />";
}
}
}?>
上面的代码无法编译。是否有一种解决方法可以让它编译和工作?
答案 0 :(得分:0)
您可以创建一个SalesTransaction
存储库作为更具体类型的存储库的包装。 (此处显示发票)
public class InvoiceAsSalesTransactionRepository : IRepostory<SalesTransaction>
{
private readonly IRepostory<Invoice> _invoiceRepository = new InvoiceRepository();
public void Add(SalesTransaction item)
{
if (item is Invoice invoice) {
_invoiceRepository.Add(invoice);
} else {
throw new ArgumentException("Item must be Invoice");
}
}
public SalesTransaction First(Expression<Func<SalesTransaction, bool>> predicate)
{
return _invoiceRepository.First(ToInvoicePredicate(predicate));
}
public SalesTransaction Single(Expression<Func<SalesTransaction, bool>> predicate,
bool disableTracking = false)
{
return _invoiceRepository.Single(ToInvoicePredicate(predicate), disableTracking);
}
private static Expression<Func<Invoice, bool>> ToInvoicePredicate(
Expression<Func<SalesTransaction, bool>> predicate)
{
var param = Expression.Parameter(typeof(Invoice), predicate.Parameters[0].Name);
return Expression.Lambda<Func<Invoice, bool>>(predicate.Body, param);
}
}
如您所见,您需要一些反射魔法来转换谓词类型。因此,您不能简单地投射您的存储库。请注意,我们不需要在此处投射任何内容,因为有效的SalesTansaction
谓词始终是有效的Invoice
谓词,因为SalesTansaction
仅包含Invoices
中也可用的属性。