Я немного работал над этим.Я не уверен, поможет ли это, но, во всяком случае, я думаю, что это может быть так.Недавно я работал с сериализацией и десериализацией класса, который мне нужно было отправить по сети.Поскольку были две разные программы (клиент и сервер), сначала я реализовал класс в обоих источниках, а затем использовал сериализацию.Это не удалось, так как .Net сказал мне, что у него не тот же идентификатор (я не уверен, но это был какой-то идентификатор сборки).
Ну, немного погуглив, я обнаружил, что это потому, что сериализованныйкласс находился в разных сборках, поэтому было решено поместить этот класс в независимую библиотеку, а затем скомпилировать клиент и сервер с этой библиотекой.Я использовал ту же идею с вашим кодом, поэтому я поместил класс Foo и класс FieldReader в независимую библиотеку, скажем:
namespace FooLibrary
{
public class Foo
{
public string Field1 = null;
public int? Field2 = null;
}
public abstract class FieldReader<T>
{
public abstract void Fill(T entity, IDataReader reader);
}
}
скомпилируйте его и добавьте в другой источник (using FooLibrary;
)
это код, который я использовал.Это не совсем то же самое, что вашдля объекта
public class ReflectionHelper
{
public static FieldReader<T> GetFieldReader<T>()
{
Type t = typeof(T);
string className = t.Name;
string readerClassName = Regex.Replace(className, @"\W+", "_") + "_FieldReader";
object[] fields = new object[10];
string source = GetFieldReaderCode(t.Namespace, className, readerClassName, fields);
CompilerParameters prms = new CompilerParameters();
prms.GenerateInMemory = true;
prms.ReferencedAssemblies.Add("System.Data.dll");
prms.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().GetModules(false)[0].FullyQualifiedName);
prms.ReferencedAssemblies.Add(t.Module.FullyQualifiedName);
prms.ReferencedAssemblies.Add("FooLibrary1.dll");
CompilerResults compiled = new CSharpCodeProvider().CompileAssemblyFromSource(prms, new string[] { source });
if (compiled.Errors.Count > 0)
{
StringWriter w = new StringWriter();
w.WriteLine("Error(s) compiling {0}:", readerClassName);
foreach (CompilerError e in compiled.Errors)
w.WriteLine("{0}: {1}", e.Line, e.ErrorText);
w.WriteLine();
w.WriteLine("Generated code:");
w.WriteLine(source);
throw new Exception(w.GetStringBuilder().ToString());
}
return (FieldReader<T>)compiled.CompiledAssembly.CreateInstance(readerClassName);
}
private static string GetFieldReaderCode(string ns, string className, string readerClassName, IEnumerable<object> fields)
{
StringWriter w = new StringWriter();
// write out field setters here
return @"
using System;
using System.Data;
namespace " + ns + ".Generated
{
public class " + readerClassName + @" : FieldReader<" + className + @">
{
public override void Fill(" + className + @" e, IDataReader reader)
" + w.GetStringBuilder().ToString() +
}
}";
}
}
, кстати, я обнаружил крошечную ошибку, вы должны использовать new или override с методом Fill, поскольку он является абстрактным.
Хорошо, я должен признать, что GetFieldReaderвозвращает ноль, но по крайней мере компилятор его компилирует.
Надеюсь, что это поможет вам или, по крайней мере, оно поможет вам найти хороший ответ в отношении