Как передать неизвестный тип функции? - PullRequest
1 голос
/ 01 ноября 2009

Я пытаюсь написать метод журнала аудита, который будет регистрировать все изменения в модели Linq-To-Sql.

Я хочу, чтобы все изменения проходили через каждый тип изменений, вызывая мой метод, который создает запись в журнале для каждого типа объекта.

Я не уверен, возможно ли это вообще.

Это мой код. Я получаю сообщение об ошибке, когда пытаюсь передать тип как typeof (original). Я не знаю тип во время разработки, поскольку это может быть любой из объектов linq в моей модели.

    ChangeSet changedObjects = this._lmsDb.GetChangeSet();

    foreach (var update in changedObjects.Updates)
    {

        Type type = update.GetType();
        var original = this._lmsDb.GetTable(type).GetOriginalEntityState(update);
        // Error from <typeof(original)>
        AuditLog au = AuditLogger.GetAuditLogRecord<typeof(original)>(original, update, "Update", "", userName);

        this._lmsDb.AuditLogs.InsertOnSubmit(au);

    }

Возможно ли это сделать? И если да, то есть ли намеки на то, как это сделать?

Ответы [ 7 ]

2 голосов
/ 01 ноября 2009

Вызов GetType на оригинал вместо попытки использовать typeof для получения его типа.

1 голос
/ 01 ноября 2009

Как насчет отражения?:

MethodInfo mi = typeof(AuditLogger).GetMethod("GetAuditLogRecord");
Type[] genericArguments = new Type[] { original.GetType() };
MethodInfo genericMI = mi.MakeGenericMethod(genericArguments);
AuditLog au = 
    (AuditLog)genericMI.Invoke(
        null, new object[] { original, update, "", userName });

Джо

0 голосов
/ 01 ноября 2009

Если GetAuditLogRecord является универсальным методом, вам не нужно указывать тип, который он использует во время компиляции - вот почему, в конце концов, вы используете универсальные методы в первую очередь:

static void Main(string[] arguments)
{
    int i = 0;
    string s = "";
    Test(i);
    Test(s);
    Console.ReadLine();
}

static void Test<T>(T arg)
{
    Console.WriteLine(arg.GetType());
}

производит:

System.Int32
System.String

Обратите внимание, что мой пример не должен быть универсальным методом; он может принимать параметр типа object и все еще работать. Методы должны быть общими, только если они создают новые переменные, используя параметры типа.

Я сомневаюсь, что вы на самом деле использовали бы дженерики для того, что вы пытаетесь сделать здесь. В дизайне, подобном тому, что вы описываете, я ожидаю, что GetAuditLog будет иметь такую ​​подпись:

AuditLogRecord GetAuditLog(IAuditable original, IAuditable current, AuditAction action, User user)

... где IAuditable предоставляет свойства / методы, которые нужны AuditLogRecord, а AuditAction - перечисление. IAuditable может выглядеть так:

interface IAuditable
{
   List<KeyValuePair<string, object>> AuditableProperties;
}

Таким образом, любой объект, который может быть проверен, отвечает за представление списка имен / значений свойств, изменения которых относятся к журналу аудита, и объекту AuditLogRecord не нужно больше ничего знать о деталях реализации объекты, которые он проверяет, чем это.

0 голосов
/ 01 ноября 2009

Если вы не знаете тип, используйте объект!

0 голосов
/ 01 ноября 2009

Если я правильно понимаю вашу проблему, вы пытаетесь использовать var и typeof () для разнородной коллекции объектов. typeof () получает тип времени компиляции, а var также типизирует время компиляции. Однако, из вашего фрагмента кода, похоже, что вы хотите определить тип во время выполнения. Как упоминалось в другом ответе, GetType даст вам тип времени выполнения, специфичный для объекта, но вы не можете использовать его в обобщенном объявлении GetAuditLogRecord.

Таким образом, в некотором смысле вам лучше придерживаться объекта в качестве вашего типа, по крайней мере, пока вы не попадете внутрь метода GetAuditLogRecord.

Я не знаю, каково происхождение ваших объектов. Если это сгенерированный код (от LINQ до SQL или Entity Framework или какого-либо другого инструмента), посмотрите, есть ли способы использовать частичные реализации класса или частичные методы для обработки ваших требований аудита. Вы также можете установить абстрактный класс, от которого наследуются все эти объекты, который реализует хотя бы часть ваших требований аудита.

0 голосов
/ 01 ноября 2009

Вам не нужно указывать тип вообще. Вывод типа сделает это за вас. Просто вызовите метод без аргумента типа: AuditLogger.GetAuditLogRecord(original, update, "Update", "", userName);

Также обратите внимание, что var вообще не является неизвестным типом. Существует определенный тип, и компилятор знает, что это такое, в противном случае он будет жаловаться на ваше присвоение переменной. В Visual Studio среда IDE сообщит вам тип, если навести курсор на ключевое слово var.

0 голосов
/ 01 ноября 2009

Вероятно, вы можете просто использовать Object в качестве типа, который принимает функция ... как выглядит ваше определение функции в настоящее время?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...