3 回答

TA貢獻1946條經(jīng)驗 獲得超4個贊
同意 Jogge 的觀點,迭代IFileBackups 會是一個更好的選擇,但是為每種類型創(chuàng)建一個接口是不行的。相反,您可以添加一個提供IEnumerable<IFileBackup>(聚合)的類。例如:
public class BackupBundle : IEnumerable<IFileBackup>
{
private readonly List<IFileBackup> _backups = new List<IFileBackup>();
// default constructor creates default implementations
public BackupBundle()
: this(new List<IFileBackup> {new BackUpMechanismA(), new BackUpMechanismB()}) {}
// allow users to add custom backups
public BackupBundle(IEnumerable<IFileBackup> backups)
{
foreach (var backup in backups)
Add(backup);
}
public void Add(IFileBackup backup)
{
if (backup == null) throw new ArgumentNullException(nameof(backup));
_backups.Add(backup);
}
public IEnumerator<IFileBackup> GetEnumerator()
{
foreach (var backup in _backups)
yield return backup;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Caller
{
private readonly IEnumerable<IFileBackup> _backups;
public Caller(IEnumerable<IFileBackup> backups)
{
_backups = backups ?? throw new ArgumentNullException(nameof(backups));
}
public async Task BackupFile(byte[] file)
{
foreach (var b in _backups)
{
try
{
await b.Backup(file);
break;
}
catch (Exception e) { }
}
}
}
注冊可按以下方式進行:
builder.RegisterInstance(new BackupBundle()).As<IEnumerable<IFileBackup>>();
builder.RegisterType<Caller>();
它允許您按類名解析:
var caller = scope.Resolve<Caller>();
如您所見,BackupBundle具有BackUpMechanismA和的依賴關(guān)系BackUpMechanismB。您可以通過引入另一層抽象來擺脫它,但我不想這樣做。我主要關(guān)心的是使Caller更健壯。您可能想要引入重試邏輯、超時等。

TA貢獻2036條經(jīng)驗 獲得超8個贊
為了使您的設(shè)計工作,您可以嘗試下一種方法:
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<BackUpMechanismA>().Keyed<IFileBackup>("A");
builder.RegisterType<BackUpMechanismB>().Keyed<IFileBackup>("B");
builder.RegisterType<Caller>()
.WithParameter((p, ctx) => p.Position == 0, (p, ctx) => ctx.ResolveKeyed<IFileBackup>("A"))
.WithParameter((p, ctx) => p.Position == 1, (p, ctx) => ctx.ResolveKeyed<IFileBackup>("B"));
IContainer container = builder.Build();
var caller = container.Resolve<Caller>();
Console.ReadKey();
}
但是在我看來,您可能在這里不需要這樣的多態(tài)性。實現(xiàn)這樣的東西會更加明顯和描述性:
public async Task BackupFile(byte[] file)
{
try
{
await BackUpToAmazonS3(file);
}
catch (AmazonS3LoadingException)
{
await BackUpToLocalDisk(file);
}
}
在這個例子中,很明顯發(fā)生了什么。在那里BackUpToAmazonS3你可以使用一些注入AmazonS3FileBackUp和BackUpToLocalDisk使用中的LocalDiskFileBackUp東西。關(guān)鍵是當(dāng)您不打算更改實現(xiàn)時,您不需要多態(tài)性。在您的上下文中應(yīng)該清楚嗎?您嘗試將備份放入某個遠程存儲,然后,如果失敗,則放入本地磁盤。您無需在此處隱藏含義。這是你的邏輯,應(yīng)該很清楚,當(dāng)你閱讀代碼時,我想。希望能幫助到你。

TA貢獻1815條經(jīng)驗 獲得超6個贊
嘗試使用名稱注冊,然后使用名稱解析:
builder.RegisterType<BackupMechanismA>().Named<IFileBackup>("BackUpMechanismA");
builder.RegisterType<BackupMechanismB>().Named<IFileBackUp>("BackUpMechanismB");
_backupA = container.ResolveNamed<IFileBackUp>
("BackUpMechanismA");
_backupB = container.ResolveNamed<IFileBackUp>
("BackUpMechanismB");
在運行時解析實例,而不是通過構(gòu)造函數(shù)注入。這將讓您根據(jù)需要解析為相應(yīng)的類型。讓我知道這個是否奏效。
- 3 回答
- 0 關(guān)注
- 222 瀏覽
添加回答
舉報