尝试创建工厂以返回通用接口(在this answer之后),但出现错误:
无法将
IFinancialsSyncService<Vendor, QuickBooksVendor>
隐式转换为IFinancialsSyncService<TEntity, TQuickBooksEntity>
。存在明显转换,您是否缺少演员表?
public class QuickBooksEntityServiceFactory
{
public IFinancialsSyncService<TEntity, TQuickBooksEntity> Create<TEntity, TQuickBooksEntity>()
where TEntity : class, IEntity, IFinancials, new()
where TQuickBooksEntity : class, IQuickBooksEntity
{
if (typeof(TEntity) == typeof(QuickBooksVendor))
{
return new QuickbooksVendorService();
}
throw new InvalidOperationException();
}
}
服务确认到IFinancialsSyncService
界面:
public class QuickbooksVendorService : IFinancialsSyncService<Vendor, QuickBooksVendor>
但是,如果我将其显式转换,则仍然会遇到Cast is redundant
错误和第一个错误。
return (IFinancialsSyncService<Vendor, QuickBooksVendor>)new QuickbooksVendorService();
因此错误使我感到困惑。我在做什么错了?
更新
这就是我要简化的内容。有许多与此类似的实例也调用了接口的其他常用方法。
switch (enumDataElement)
{
//Export jobs
case DataElement.Item:
var itemService = new QuickbooksItemService();
exportResult = itemService.UpdateMozzoEntityWithFinancialsId(session, response, EntityId, intUserId);
break;
case DataElement.Vendor:
var VendorService = new QuickbooksVendorService();
exportResult = UpdateMozzoEntityWithFinancialsId(new QuickbooksVendorService(),session, response, EntityId, intUserId);
break;
case DataElement.Bill:
var billService = new QuickbooksBillService();
exportResult = billService.UpdateMozzoEntityWithFinancialsId(session, response, intUserId);
break;
case DataElement.PurchaseOrder:
var qbPOService = new QuickbooksPurchaseOrderService();
exportResult = qbPOService.UpdateMozzoEntityWithFinancialsId(session, response, intUserId);
break;
case DataElement.SalesReceipt:
var salesReceiptService = new QuickbooksSalesReceiptService();
exportResult = salesReceiptService.UpdateStratusEntityWithFinancialsId(session, response, intUserId);
break;
}
并替换为:
var qbEntityService = EntityServiceFactory.Create(enumDataElement);
这家工厂长什么样?
答案 0 :(得分:1)
这与Liskov的替代原则有关。想象一下,您的通用类型是接口的属性:
public interface IFinancials { }
public interface IFinancialsSyncService
{
IFinancials Financials { get; set; }
}
现在我们实现以下接口:
public class Financials : IFinancials {}
public class FinancialsSyncService : IFinancialSyncService
{
public Financials Financials { get; set; }
}
这会导致编译器错误:
编译错误:“ Program.FinancialsSyncService”未实现接口成员“ Program.IFinancialsSyncService.Financials”。 “ Program.FinancialsSyncService.Financials”无法实现“ Program.IFinancialsSyncService.Financials”,因为它没有匹配的返回类型“ Program.IFinancials”。
两个问题都有相同的问题。在我的示例中,接口声明结果为IFinancials
类型,但是更具体的派生类型Financials
,即使属性中放置的任何有效值都满足该接口,也无法替换具有从IFinancials
派生的任何值,只有从Financials
派生的类型。
因此,如果您的代码如下所示:
public interface IFinancialsSyncService<TEntity>
where TEntity : IEntity
{
TEntity Financials { get; set; }
}
然后您创建一个类:
public class QuickbooksVendorService : IFinancialSyncService<Vendor>
{
public Vendor Financials { get; set; }
}
但是,现在QuickbooksVendorService
是IFinancialSyncService<Vendor>
而不是IFinancialSyncService<TEntity>
,因为该属性是派生类型。即使您没有此特定属性,它仍然会导致相同的问题,即泛型类型比接口更特定。
答案 1 :(得分:-1)
使用Factory方法和适配器模式
[TestFixture]
public class Class1
{
[Test]
public void Go()
{
var qbItem = Export(1);
var qbVendor= Export(2);
var qbSales= Export(3);
}
public qbEntityService Export(int number)
{
var qb = Class1.Create(number);
return qb.UpdateMozzoEntityWithFinancialsId();
}
public static IEntityService Create(int enumDataElement)
{
switch (enumDataElement)
{
case 1:
return new QuickbooksItemService();
case 2:
return new QuickbooksVendorService();
case 3:
return new QuickbooksSalesReceiptServiceAdapter(new QuickbooksSalesReceiptService());
default:
throw new Exception();
}
}
}
public interface IEntityService
{
qbEntityService UpdateMozzoEntityWithFinancialsId();
}
public class qbEntityService
{
}
public class QuickbooksItemService : IEntityService
{
public qbEntityService UpdateMozzoEntityWithFinancialsId()
{
Console.WriteLine("I am QuickbooksItemService, performing UpdateMozzoEntityWithFinancialsId");
return new qbEntityService();
}
}
public class QuickbooksVendorService : IEntityService
{
public qbEntityService UpdateMozzoEntityWithFinancialsId()
{
Console.WriteLine("I am QuickbooksVendorService, performing UpdateMozzoEntityWithFinancialsId");
return new qbEntityService();
}
}
public class QuickbooksSalesReceiptService
{
public qbEntityService UpdateStratusEntityWithFinancialsId()
{
Console.WriteLine("I am QuickbooksSalesReceiptService, performing UpdateStratusEntityWithFinancialsId");
return new qbEntityService();
}
}
public class QuickbooksSalesReceiptServiceAdapter : IEntityService
{
private QuickbooksSalesReceiptService adaptee;
public QuickbooksSalesReceiptServiceAdapter(QuickbooksSalesReceiptService adaptee)
{
this.adaptee = adaptee;
}
public qbEntityService UpdateMozzoEntityWithFinancialsId()
{
return adaptee.UpdateStratusEntityWithFinancialsId();
}
}