Я использую System.Reflection.Emit
TypeBuilder
для генерации нескольких пользовательских классов .NET с методами экземпляра.Например:
public class EmittedClass
{
public bool TryGetName(out string value)
{
...
}
public bool TryGetAge(out int value)
{
...
}
}
Все методы имеют одну и ту же сигнатуру, которая может быть описана общим делегатом:
public delegate bool TryGetter<T>(out T value);
Конечно, я хотел бы иметь возможность явно указать цельэкземпляр на сайте вызова, например:
var instance = InstanceFactory.CreateInstance();
var tryGetName = InstanceFactory.CreateTryGetter<string>("Name");
string name;
if (tryGetName(instance, out name)) // Problem here.
{
...
}
Чтобы это работало, мне нужно превратить делегата в так называемый открытый делегат :
public delegate bool TryGetter<T>(object instance, out T value);
Поскольку у меня нет типа времени компиляции целевого экземпляра, мне нужно передать его как System.Object
.Однако, это прерывается во время выполнения, потому что метод экземпляра ожидает, что его 'this' будет иметь тип декларирующего класса.Ой.
Решение, которое я сейчас использую, заключается в создании промежуточного лямбда-выражения, которое принимает входной объект, выполняет приведение во время выполнения к целевому типу, а затем переходит к вызову целевого метода.Это работает, но я чувствую себя неловко из-за этого клуджа в середине.
Вопрос в том, могу ли я каким-то образом изменить мои испускаемые методы так, чтобы их this
аргументы принимали любые System.Object
и до сих порсохранить проверяемый код?
Если нет, я думаю, что я все еще могу избежать промежуточной лямбды, сделав методы статичными и выполняя приведение в их тела.В идеале, однако, я бы хотел вообще избежать кастинга, но я подозреваю, что в управляемом мире этого не может быть из-за того, как работает проверка CIL и загрузка метаданных.
Просто интересно, не знает ли кто-нибудь больше о CILможете дать мне совет на эту тему.Спасибо!
ОБНОВЛЕНИЕ: Проблема, которую я пытаюсь решить
Классы имеют свойства, которые обычно поддерживаются полями.Это хорошо, если ожидается, что экземпляры указанных классов будут поддерживать только одно состояние за один раз.Под состоянием я подразумеваю комбинацию значений в полях экземпляра в определенный момент времени.
Моим бизнес-требованием является внедрение альтернативного хранилища, чем простых полей, которое позволит одному экземпляру класса иметь более одного состояния одновременновремя.Побочной целью этого требования является сделать это как можно более эффективным как с точки зрения памяти, так и с точки зрения скорости доступа.
Основная идея моего подхода заключается в создании зеркального отображения бизнес-класса с использованием * 1040.* и бизнес-класс должен поддерживать набор этих экземпляров, каждый из которых соответствует определенному состоянию.Естественно, методы получения и установки бизнес-класса должны быть подключены к соответствующим методам в экземпляре состояния.Здесь задействовано гораздо больше деталей, но это основная идея.
Я надеюсь, что объяснение поможет понять причину, по которой я задаю этот вопрос.Я ценю, что многим это может показаться чрезмерной разработкой, но другие альтернативы, которые не включают System.Reflection.Emit
, слишком медленны и требуют много ресурсов.Я не могу этого.