2009-11-01 3 views
1

Я пытаюсь написать метод журнала аудита, который будет регистрировать все изменения в модели 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); 

    } 

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

+0

В java все распространяется от класса Object, я не знаю, является ли это хорошим способом или даже если C# поддерживает это, но можете ли вы отправить typeof (Object)? Простое предложение, возможно, не ответ. –

ответ

1

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

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

Спасибо, Джо. Это потрясающе! – littlechris

0

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

2

Позвоните GetType по телефону оригинал вместо того, чтобы пытаться использовать typeof для получения его типа.

0

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

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

0

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

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

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

0

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

0

Если 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 объект не нужно знать ничего больше о деталях реализации объектов, которые он одитирует, чем это.

Смежные вопросы