如何为正在使用的类型 return 编写扩展方法?
How to write an extension method to return the type being used?
我有一个允许用户关闭延迟加载的扩展方法。
public static IBaseEntityService<TEntity, TPrimaryKey> EnableLazyLoading<TEntity, TPrimaryKey>(
this IBaseEntityService<TEntity, TPrimaryKey> baseService,
bool enabled)
where TEntity :Entity<TPrimaryKey> where TPrimaryKey : struct
{
baseService.UnitOfWork.EnableLazyLoading(enabled);
baseService.UnitOfWork.EnableProxyCreation(enabled);
var type = baseService.GetType().;
return (type)baseService;
}
这是基本界面的示例:
public interface IBaseEntityService<TEntity,TPrimaryKey> :
IBaseService<TEntity, TPrimaryKey>
where TEntity: Entity<TPrimaryKey> where TPrimaryKey : struct
{
TEntity FindByTenantId(Guid tenantId);
IBaseEntitySpecification<TEntity,TPrimaryKey> Specification { get; }
}
假设我有实现 IBaseEntityService<TEntity,TPrimaryKey>
接口的服务:
public IUserService: IBaseEntityService<User,int>
{
User FindByUserName(string username);
}
这是我想要实现的目标:
var user = _userService.EnableLazyLoading(false).FindByUserName("someUsername");
正如您在我的示例中看到的那样,在 EnableLazyLoading(false)
之后,我可以进入 FindByUserName
方法。目前,因为它只有 return 一个 IBaseEntityService,所以我没有那个选项。
我想确保扩展方法知道 return IUserService
,因为它实现了 IBaseEntityService
。我知道它必须在某个时候转换它,我想避免为 IUserService
编写相同 EnableLazyLoading
方法的特定实现
我想到了这样的事情,但似乎我可以做一些事情而不必隐式调用 Cast 方法:
public static TEntityService Cast<TEntity, TPrimaryKey, TEntityService>(
this IBaseEntityService<TEntity, TPrimaryKey> baseEntityService)
where TEntity : Entity<TPrimaryKey>
where TPrimaryKey : struct
where TEntityService : IBaseEntityService<TEntity, TPrimaryKey>
{
return (TEntityService) baseEntityService;
}
所以它可能会像这样工作:
var user = _userService.EnableLazyLoading(false).Cast<IUserService>().FindByUserName("someUsername");
Ben in 提供的最佳解决方案是:
public static T EnableLazyLoading<T, TEntity, TKey>(
this T @this,
bool enabled)
where T : IBaseService<TEntity, TKey>
where TEntity : Entity<TKey>
where TKey : struct
{
@this.UnitOfWork.EnableLazyLoading(enabled);
@this.UnitOfWork.EnableProxyCreation(enabled);
return @this;
}
另一个更便宜但不干净的解决方案是使用 dynamic
关键字:
public static dynamic EnableLazyLoading<TEntity, TPrimaryKey>(
this IBaseEntityService<TEntity, TPrimaryKey> @this,
bool enabled)
where TEntity : Entity<TPrimaryKey>
where TPrimaryKey : struct
{
@this.UnitOfWork.EnableLazyLoading(enabled);
@this.UnitOfWork.EnableProxyCreation(enabled);
return @this;
}
代价是您失去了 IntelliSense 的便利性,并且可能失去了一些性能。
您可以将 EnableLazyLoading
的接收者设为限制为 IBaseService
的通用类型。它很罗嗦,但应该可以解决问题。
public static TService EnableLazyLoading<TService, TEntity, TKey>(this TService service)
where TService : IBaseService<TEntity, TKey>
where TEntity : Entity<TKey>
where TKey : struct
{
// do stuff
return service;
}
这样,您将获得 return 类型的实际服务类型。我有一段时间没有用过 C#,所以我可能会忘记一些重要的事情,但是 IIRC 这个工作得很好。
我有一个允许用户关闭延迟加载的扩展方法。
public static IBaseEntityService<TEntity, TPrimaryKey> EnableLazyLoading<TEntity, TPrimaryKey>(
this IBaseEntityService<TEntity, TPrimaryKey> baseService,
bool enabled)
where TEntity :Entity<TPrimaryKey> where TPrimaryKey : struct
{
baseService.UnitOfWork.EnableLazyLoading(enabled);
baseService.UnitOfWork.EnableProxyCreation(enabled);
var type = baseService.GetType().;
return (type)baseService;
}
这是基本界面的示例:
public interface IBaseEntityService<TEntity,TPrimaryKey> :
IBaseService<TEntity, TPrimaryKey>
where TEntity: Entity<TPrimaryKey> where TPrimaryKey : struct
{
TEntity FindByTenantId(Guid tenantId);
IBaseEntitySpecification<TEntity,TPrimaryKey> Specification { get; }
}
假设我有实现 IBaseEntityService<TEntity,TPrimaryKey>
接口的服务:
public IUserService: IBaseEntityService<User,int>
{
User FindByUserName(string username);
}
这是我想要实现的目标:
var user = _userService.EnableLazyLoading(false).FindByUserName("someUsername");
正如您在我的示例中看到的那样,在 EnableLazyLoading(false)
之后,我可以进入 FindByUserName
方法。目前,因为它只有 return 一个 IBaseEntityService,所以我没有那个选项。
我想确保扩展方法知道 return IUserService
,因为它实现了 IBaseEntityService
。我知道它必须在某个时候转换它,我想避免为 IUserService
EnableLazyLoading
方法的特定实现
我想到了这样的事情,但似乎我可以做一些事情而不必隐式调用 Cast 方法:
public static TEntityService Cast<TEntity, TPrimaryKey, TEntityService>(
this IBaseEntityService<TEntity, TPrimaryKey> baseEntityService)
where TEntity : Entity<TPrimaryKey>
where TPrimaryKey : struct
where TEntityService : IBaseEntityService<TEntity, TPrimaryKey>
{
return (TEntityService) baseEntityService;
}
所以它可能会像这样工作:
var user = _userService.EnableLazyLoading(false).Cast<IUserService>().FindByUserName("someUsername");
Ben in
public static T EnableLazyLoading<T, TEntity, TKey>(
this T @this,
bool enabled)
where T : IBaseService<TEntity, TKey>
where TEntity : Entity<TKey>
where TKey : struct
{
@this.UnitOfWork.EnableLazyLoading(enabled);
@this.UnitOfWork.EnableProxyCreation(enabled);
return @this;
}
另一个更便宜但不干净的解决方案是使用 dynamic
关键字:
public static dynamic EnableLazyLoading<TEntity, TPrimaryKey>(
this IBaseEntityService<TEntity, TPrimaryKey> @this,
bool enabled)
where TEntity : Entity<TPrimaryKey>
where TPrimaryKey : struct
{
@this.UnitOfWork.EnableLazyLoading(enabled);
@this.UnitOfWork.EnableProxyCreation(enabled);
return @this;
}
代价是您失去了 IntelliSense 的便利性,并且可能失去了一些性能。
您可以将 EnableLazyLoading
的接收者设为限制为 IBaseService
的通用类型。它很罗嗦,但应该可以解决问题。
public static TService EnableLazyLoading<TService, TEntity, TKey>(this TService service)
where TService : IBaseService<TEntity, TKey>
where TEntity : Entity<TKey>
where TKey : struct
{
// do stuff
return service;
}
这样,您将获得 return 类型的实际服务类型。我有一段时间没有用过 C#,所以我可能会忘记一些重要的事情,但是 IIRC 这个工作得很好。