我不是 C# 的新手,但我并没有真正使用泛型和 DI,但我遇到了一个自学项目,所以我捕获了这个机会。这是场景(会很长,感谢您的耐心等待)...
我们有一个托管网络服务的本地解决方案。我有一个应用程序可以访问这些网络服务来为我们的合作伙伴之一提取信息并生成数据文件。 我们正在从本地解决方案转向基于云的解决方案(相同的供应商,相同的网络服务,在云中的实现略有不同)。 我决定最好通过执行以下操作来学习接口(interface)(比我现在知道的更多)、泛型(我在输入时正在学习)和依赖注入(inject)(也是该特定领域的初学者)
为我正在调用的每个 Web 服务创建一个接口(interface),即 IGetUsers 和函数 CallUserService 返回列表 云解决方案和本地解决方案各实现一次接口(interface)
public class GetUsersCloud : IGetUsers { public List<string> CallUserService(int ID)... }
public class GetUsersPrems : IGetUsers { public List<string> CallUserService(int ID)... }
现在我有一个带有构造函数的类,该类采用 IGetUsers 的实例
public class GetUsers {
private IGetUsers _getUsers;
public GetUsers(IGetUsers getUsers) {
_getUsers = getUsers;
}
从这里我可以使用处理本地解决方案或云解决方案的类的实例来实例化此类,然后调用
GetUsers getUsers;
if (!cloud) {
getUsers = new GetUsers(new GetUsersPrems());
} else {
getUsers = new GetUsers(new GetUsersCloud());
}
List<string> userList = getUsers.CallUserService(5);
这很好用,因为我的返回类型是一个列表,所以我可以很容易地处理它。这是我有点卡住的地方。
我有另一个接口(interface)要实现,但是实现它的类将返回不同类型的 web 服务。我的意思是,虽然这两个 Web 服务将返回一个名为 UserDetailList 的类型,但它们来自两个不同的强类型类,这些类是通过从本地和云解决方案导入服务引用而创建的。为了处理这个问题,我创建了一个接口(interface),其中包含一个返回泛型的函数
public interface IUserDetails {
T GetUserDetails<T>(int ID);
}
我的类实现看起来像这样(显然缺少肉和土 bean ,但你明白了)
public class GetUserDetailsCloud : IUserDetails {
public T FetchUserDetails<T>(int ID) {
CloudWS.UserDetailList userDetailList = cloudWebservice.GetUserDetailList(ID);
return (T)(object)userDetailList;
}
}
public class GetUserDetailsPrems : IUserDetails {
public T FetchUserDetails<T>(int ID) {
PremsWS.UserDetailList userDetailList = premsWebservice.GetUserDetailList(ID);
return (T)(object)userDetailList;
}
}
我创建了一个带有构造函数的类,该构造函数采用 IUserDetails 的实例
public class GetUserDetails{
private IUserDetails _getUserDetails;
public GetUserDetails(IUserDetails getUserDetails) {
_getUserDetails= getUserDetails;
}
}
现在很简单,我可以根据我是否在云端进行实例化:
GetUserDetails getUserDetails;
object userDetailsResults;
if (!cloud) {
getUserDetails = new GetUserDetails (new GetUserDetailsPrems());
userDetailsResults = getUserDetails.FetchUserDetails<PremsWS.UserDetailList>(ID);
} else {
getUserDetails = new GetUserDetails (new GetUserDetailsCloud());
userDetailsResults = getUserDetails.FetchUserDetails<CloudWS.UserDetailList>(ID);
}
这是我卡住的地方。由于这两个 web 服务有不同的类型,我调用它并根据我是否是云来传递类型,然后我的结果存储在一个对象中而不是强类型类的实例。我接下来的步骤涉及遍历结果和执行操作/填充输出文件。我曾经可以说,一种类型...
foreach (PremsWS.UserDetail in userDetailsResults) {
<do some trivial stuff here>
}
现在在我看来,我必须编写两个单独的函数来遍历数据并处理结果。我觉得应该有一种方法可以让我编写一个接受通用类型的函数,然后根据它是什么(无论是云实例还是本地实例)处理结果。
我一直坐在这里试图弄明白,但我的谷歌未能找到教程或任何可以指引我正确方向的东西,我将不胜感激。
最佳答案
这里的理想路径是只从 GetUserDetailList
返回相同的类型。由于这似乎不是一种选择,因此将两种返回类型视为同名对实现它们的分离造成了一点伤害。
它们也可能返回类型 Web
和 Local
。此外,您似乎没有能力更改 UserDetailList
类型。
因此,您唯一可以引入修复的地方就是消费点。一旦拥有强类型实例,就需要对其进行抽象。这里最好的方法是使用复制构造函数来促进抽象,因为您至少知道这些属性。
public class LocalUserDetailList
{
public [[ underlying name and type for the UserList data ]] { get; set; }
public LocalUserDetailList(PremsWS.UserDetailList UserDetailList)
{
// populate the publicly available list above^
}
public LocalUserDetailList(CloudWS.UserDetailList UserDetailList)
{
// populate the publicly available list above^
}
}
现在您可以使用此复制构造函数来返回统一类型以供使用。
public interface IUserDetails
{
LocalUserDetailList FetchUserDetails(int ID);
}
public class GetUserDetailsCloud : IUserDetails {
public LocalUserDetailList FetchUserDetails(int ID) {
CloudWS.UserDetailList userDetailList = cloudWebservice.GetUserDetailList(ID);
return new LocalUserDetailList(userDetailList);
}
}
public class GetUserDetailsPrems : IUserDetails {
public LocalUserDetailList FetchUserDetails(int ID) {
PremsWS.UserDetailList userDetailList = premsWebservice.GetUserDetailList(ID);
return new LocalUserDetailList(userDetailList);
}
}
最后从您的调用中访问没有 object
的统一实例。
GetUserDetails getUserDetails;
LocalUserDetailList userDetailsResults;
if (!cloud) {
getUserDetails = new GetUserDetails (new GetUserDetailsPrems());
userDetailsResults = getUserDetails.FetchUserDetails(ID);
} else {
getUserDetails = new GetUserDetails (new GetUserDetailsCloud());
userDetailsResults = getUserDetails.FetchUserDetails(ID);
}
虽然这不使用泛型,但它确实有效,并且易于阅读和调试。有时,泛型会变得草率,在这种情况下就是这样。如果您一直使用对象作为类型,则需要您使用属性迭代才能在迭代期间获取值。这并不理想,速度很慢,并且会导致代码很难阅读。
此外,使用这样的抽象还应该允许您在代码中实现可以删除重复调用并仅返回一个副本构造函数实例的地方。如果您随后要利用具有泛型的抽象版本,那将是使用该工具的更强大和集成的方式。
关于c# - 在 C# 中,一个类可以返回两种不同类型的对象,需要循环遍历它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58123630/