我想在"平台"中定义一个注射依赖项。部件。我想要使用程序集来注入依赖项,但我不希望它们能够直接使用它。换句话说,我希望依赖本身是公开的,但依赖的方法是内部的。显然,您无法使用内部方法定义公共接口。
我想出了一个解决方案,但我想知道是否采用更清洁的方法。基本上,我不是定义一个接口,而是采用C ++启发的方法并定义一个纯抽象类。整件事情看起来像这样:
在"平台"组装
public abstract class IDependency
{
public abstract void DoSomethingPublic();
internal abstract void DoSomethingInternal();
}
public class DependencyImplementation : IDependency
{
public override void DoSomethingPublic()
{
...
}
public override void DoSomethingInternal()
{
...
}
}
public class Consumer
{
public void Consume(IDependency dependency)
{
...
dependency.DoSomethingInternal();
...
}
}
消费组装:
var consumer = new Consumer();
var dependency = new DependencyImplementation();
consumer.Consume(dependency);
这可以做我想要的一切,但它看起来像是一个hacky解决方案。是否有另一种解决这个问题的方法,或者这是一个可接受的解决方案?
修改:这是我实际问题的一个更具体的例子。我有一个平台组件和一个网站组件。在我的平台程序集中,我有以下扩展方法:
public static bool HasSettingEnabled(this IUser user, ISettingFactory factory)
{
var settingEntity = factory.GetOrCreateByUserId(user.Id);
return settingEntity.IsEnabled || user.ShouldForciblyEnableSetting;
}
在我的网站程序集中,我可以通过调用user.HasSettingEnabled()
或直接从工厂获取设置来检查设置是否已启用。但是,我想限制网站程序集直接通过工厂检查设置,因为强制启用设置的逻辑将被遗漏。所以我希望我的ISettingFactory可以从网站上注入,但我不希望能够在平台之外调用ISettingFactory.GetOrCreateByUserId()。使用上面的模式,您可以获得以下内容:
平台组装:
public abstract class ISettingFactory
{
internal abstract Setting GetOrCreateByUserId(int userId);
}
public class SettingFactory : ISettingFactory
{
internal override Setting GetOrCreateByUserId(int userId)
{
// Get setting entity from DB
...
return setting;
}
}
public static class IUserExtension
{
public static bool HasSettingEnabled(this IUser user, ISettingFactory factory)
{
var settingEntity = factory.GetOrCreateByUserId(user.Id);
return settingEntity.IsEnabled || user.ShouldForciblyEnableSetting;
}
}
在网站集中:
var settingFactory = new SettingFactory();
if (user.HasSettingEnabled(settingFactory))
{
// Do something.
...
}
所以你可以看到网站只注入工厂而且永远不能直接获取或创建方法。这保证了只有一个代码路径可以获得用户的设置。
答案 0 :(得分:1)
我不确定我100%理解你想要什么 - 是消费者提供的界面的实现吗?或者平台程序集是否包含IDependency的所有实现?在后一种情况下,也许内部接口可以提供帮助。
公共类可以实现内部接口。因此,您可以将所有内部方法放在内部接口中,将所有公共方法放在公共方法中,只暴露公众。这样,您可以在平台程序集中使用IInternalDependency
,但只公开IDependency
。
public interface IDependency
{
void DoSomethingPublic();
}
internal interface IInternalDependency : IDependency
{
void DoSomethingInternal();
}
public class YourClass: IInternalDependency
{
public void DoSomethingPublic()
{
}
// Note the Explicit interface member implementation
void IInternalDependency.DoSomethingInternal()
{
}
}
在您的消费者代码中,您必须尝试投射它:
public void Consume(IDependency dependency)
{
var intDependency = dependency as IInternalDependency;
if(intDependency == null)
{
throw new InvalidOperationException();
}
intDependency.DoSomethingInternal();
}