Определите интерфейс, который должны реализовывать все ваши плагины:
public interface IPlugin {
string Name { get; }
string Author { get; }
string Description { get; }
void Init();
}
А затем используйте Dictionary<Type, IPlugIn>
.
Обычно интерфейс объявляется в отдельной dll (например, «MyCompany.MyProject.PlugIns.Contracts.dll»).
РЕДАКТИРОВАТЬ: Хорошо, я думаю, что я знаю, что вы имеете в виду сейчас.
Хитрость заключается в том, чтобы иметь общий класс между Field
и UsernameField
с помощью универсального метода Set
. Тот факт, что Field
не является общим, делает все типы полей, назначаемые ему. Это было бы не так, если бы он был объявлен как Field<T>
.
public abstract class Field
{
}
public abstract class GenericField<T> : Field
{
public void Set(DynamicObject obj, T value)
{
obj[this.GetType()] = value;
}
}
public class UsernameField : GenericField<string>
{
#region Singleton Pattern
public static readonly UsernameField Instance = new UsernameField();
private UsernameField() { }
#endregion
}
Поскольку нам нужно вызвать GetType
в методе Set
, мы не можем объявить его как static
. Поэтому я использовал шаблон синглтона.
Теперь мы можем установить поле безопасным способом:
UsernameField.Instance.Set(obj, "Joe");
ДОПОЛНЕНИЕ 1:
Поскольку теперь поля являются синглетонами, вы можете использовать поля в качестве ключа словаря вместо их типа.
public class DynamicObject : IDictionary<Field, object> { }
И Set
станет:
public void Set(DynamicObject obj, T value)
{
obj[this] = value;
}
ДОПОЛНЕНИЕ 2:
Вы также можете определить DynamicObject
так:
public class DynamicObject : Dictionary<Field, object>
{
public void Set<T>(GenericField<T> field, T value)
{
this[field] = value;
}
}
Теперь вы можете установить значения следующим образом:
obj.Set(UsernameField.Instance, "Sue");
Это безопасный тип и кажется более естественным. Set
метод в GenericField
устарел.