How to convert PropertyInfo[] to my class - c#

I'm developing an .NET Core 3.1 API, and I had a situation where I needed to iterate an object using foreach. To be able to do this, I used Reflection:
var properties = myClass.GetType().GetProperties();
After that, the code goes through the foreach as normal, and then I return the modified properties object to an external API, but it returns a timeout error message, I think it is because the PropertyInfo[] class isn't very appropriate for returning like this, or it's something else, I don't know.
Because of that, I want to convert properties "back" to myClass, or maybe convert it into an dictionary, it would be better to return the original class instead of PropertyInfo[].
How can I convert PropertyInfo[] into a class?
Thanks!

It sounds like you're trying to serialize this class to send to an API. What format does your API accept? If it accepts e.g. json, you should just use a json serializer (like JSON.net - which uses things like reflection under the hood anyways). If you are trying to serialize to a more exotic or unsupported format, then you can do it this way. What's missing is that the Properties[] array doesn't contain the values of your properties, only the definition. You can use the properties array to fetch the values:
public class MyClass
{
public int a { get; set;}
public string b {get; set; }
}
void Main()
{
var instance = new MyClass{a=1,b="2"};
var properties = instance.GetType().GetProperties();
var value_of_a = properties.First(p => p.Name == "a").GetValue(instance);
}
Each property has a "GetValue" method on it that can extract the value corresponding to that property from the class the property came from - note that up above you call 'GetType()' before you call 'GetProperties' - this means you're getting properties for the Type, not the instance. You then need to take those property definitions back to the instance to get the property values.

Related

Is it possible to set custom (de)serializers for open generic types in ServiceStack.Text?

I have a type like this:
class Foo<T>
{
public string Text { get; set; }
public T Nested { get; set; }
public static string ToJson(Foo<T> foo) { [...] }
}
ToJson serializes a Foo<Bar> instance to JSON in a way that is impossible to achieve by tweaking JsConfig. Also, ToJson relies on ServiceStack.Text to serialize Nested, which can be an instance of Foo<Baz>.
Unfortunately, the way JsConfig is implemented implies that there will be a JsConfig<T> set of static variables for Foo<Bar> and other for Foo<Baz>. Also, AFAIK, ServiceStack.Text offers no way to configure JSON serialization for open generic types (i.e.: something like JsConfig.Add(typeof(Foo<>), config)). I tried to solve this issue by creating this static constructor for Foo<T>:
static Foo() {
JsConfig<Foo<T>>.RawSerializeFn = ToJson;
}
This doesn't work all the time. It depends on the order the static constructors are invoked by the runtime. Apparently, ServiceStack.Text caches serializers functions and sometimes is doing it before the static constructor is called depending on the order operations are invoked in the API, so:
var outer = new Foo<Baz> { Text = "text" };
outer.ToJson(); // OK, because Nested is null
var inner = new Foo<Bar>();
inner.ToJson(); // OK, because JsConfig<Foo<Bar>>.RawSerializeFn is Foo<T>.ToJson
outer.Nested = inner;
outer.ToJson(); // NOT OK, because SS.Text uses the default serializer for Foo<T>, not Foo<T>.ToJson
I can't set all the serializers in JsConfig<Foo<T>> beforehand because T can be virtually any type, even other generic types.
Is it possible to define custom serialization routines for open generic types (that can be nested) in ServiceStack.Text?
I solved for this in my own way with a wrapper and a custom deserializer. I created a base type for all of my abstract types. That base type tells the system which type it is:
public class SetSettingItemBase
{
public string Key { get; set; }
public string ValueType { get; set; }
}
So the base is essentially the metadata -- the setting key + the value type. The object DTO, then, simply extends it by adding the actual value:
public class SetSettingItem : SetSettingItemBase
{
public object Value { get; set; }
}
Note that it's just an object. This is the DTO, not my actual object. I can cast it later, or convert it to a real/generic type after serialization.
My custom serialization then is:
JsConfig<SetSettingItem>.RawDeserializeFn = str =>
{
var baseSettings = str.FromJson<SetSettingItemBase>();
var ret = baseSettings.MapTo<SetSettingItem>();
if(true) // actual condition removed here... unimportant to the example
{
var dataType = Constants.KnownSettingsTypes[baseSettings.ValueType];
var method = typeof(JsonExtensions).GetMethod("JsonTo").MakeGenericMethod(dataType);
var key = "Value";
var parsed = JsonObject.Parse(str);
if(parsed.Object(key) == null)
key = "value";
ret.Value = method.Invoke(null, new object[] { parsed, key });
}
return ret;
};
This method first deserializes to the simple base. So the Value passed in from the DTO is ignored when deserializing baseSettings. I then call MapTo to prepare the actual SetSettingItem DTO. MapTo is just a wrapper around AutoMapper. You could just as easily use SS's built in mapper here.
For security, I have a set list of types that I allow as settings. Example:
KnownSettingsTypes.Add("string", typeof(string));
KnownSettingsTypes.Add("int", typeof(int));
KnownSettingsTypes.Add("nullableint", typeof(int?));
KnownSettingsTypes.Add("nullablepercentage", typeof(double?));
KnownSettingsTypes.Add("feegrid", typeof(FeeGrid));
After that, I use reflection to get the JsonTo method, passing in the generic type parameter dynamically from the KnownSettingsTypes dictionary.
And then finishing it all up, I parse the object using the generic JsonObject.Parse method and then looking for the Value or value (depending on case sensitivity) and explicitly convert that JsonObject using the dynamic method I created earlier.
The end result is I can pass in settings of all different types here as a part of my DTOs.
This served my purposes for the time being, but looking at the example I could see it improving in two ways:
After parsing, I could convert my SetSettingItem to a SettingItem<T> so I could use it as a strongly-typed object in my code. Remember, this example is just for the DTOs to get it across the wire.
Instead of requiring the person to pass in the type for me to check against, I could check against the setting Key to know which type it is supposed to be and parse accordingly. In my example, even if I check against the master list of settings and their types, I'd still probably require them to pass in the type just as a precaution and throw an exception if they didn't match.

Entity Framework - access fields by number

I'm working with Entity Framework (v4) under Visual Studio 2010 (going against an Oracle database).
A record has been read in as follows:
MYTABLE_DEF t;
t = db.MYTABLE_DEF.Find(identifier);
Now, I know I can access the fields in t directly:
Console.WriteLine(t.SOMEVALUE);
What I would like to be able to do is reference the fields in t, either by doing some sort of 'index' (something like t[0] for first field, t[1] for second field). If that's not possible, then is it possible to bind the field at run time? Something like:
string whichfield = Console.ReadLine();
Console.WriteLine(t[whichfield]) // I know this won't work
I've basically been learning Entity Framework through trial and error (and google) but haven't come across anything sort of indirect reference like that.
Assuming MYTABLE_DEF is an ordinary Entity Class, you should be able to simply reflect over the public fields and return the nth one. Something like this: (untested)
public object this[int index]
{
Type myType = this.GetType();
PropertyInfo[] myProperties =
myType.GetProperties(BindingFlags.Public|BindingFlags.Instance);
object result = myProperties[myIndex].GetValue(myClassInstance, null);
return result;
}
For convenience, I would write this as an extension method on object:
public static Property IndexedProperty(this object obj, int index)
{
Type myType = obj.GetType();
PropertyInfo[] myProperties =
myType.GetProperties(BindingFlags.Public|BindingFlags.Instance);
return myProperties[myIndex];
}
which you can then call thusly:
var theSixthProperty = myObject.IndexedProperty(6);
var valueOfSixthProperty = theSixthProperty.GetValue();
Having it as an Extension Method eliminates the problem of having to write an indexer for every Entity Class.

C#: Create instance of a type based on an integral Enum value

I have an interface for implementing an "output formatter" that looks a bit like this:
public interface IFormatOutput {}
public class HtmlOutputFormatter : IFormatOutput {}
public class TextOutputFormatter : IFormatOutput {}
// etc, etc...
public enum OutputFormat {
Html,
Text,
HappyMeal,
Excel
}
public class SomeFormattableEntity {
int Id { get; set; }
OutputFormat OutputType { get; set; }
}
So SomeFormattableEntity is persisted in a database via Dapper and its OutputType property is stored as the underlying integer value (ie, in an INT column). As you can guess, I want to provide an instance of a IFormatOutput to handle a SomeFormattableEntity based on its OutputType property.
Is there some clean best-practice way to handle this type of relationship? My ideas so far include a factory with innards potentially consisting of:
grandpa's horrible ugly switch statement
an array mapping the enum value to a Type
reflection-based magic mapping enum member name as string to class type elsewhere
some mapping mechanism involving attributes
I realize it is not desirable to require an instance of a thing whose type is based on a value, but it seems hard to avoid this when SQL is involved. Basically the problem is that multiple "things" that all have varying .NET types are stored in a single table. I keep running into this idiom and am unable to find an elegant solution to it.
I'd probably go for a custom attribute with a FormatsOutputFor property. Then decorate all of your implementations of IFormatOutput with the attribute. e.g.
[YourAttribute(OutputFormat.Html)]
public class HtmlOutputFormatter : IFormatOutput {}
Then in your factory:
// get all your formatters
var formatters = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => Attribute.IsDefined(p, typeof(YourAttribute)));
// Now go through each formatter and use the attribute to figure out which
// output format it's for. Add these to some static IDictionary<OutputFormat, Type>
You probably want to build some internal cache that maps an OutputFormat value to a Type. Then your factory can double check that you have only got one type mapped to each output format and if you try to get a formatter for an enum value that doesn't have a corresponding class then you wont get some obscure TypeLoadException from activator.
Hopefully that makes sense...
How about:
OutputFormat format = OutputFormat.Excel;
object obj = Activator.CreateInstance("myAssemblyName", format.ToString());
Assuming the elements of your enum has the exact name of your types?

How to serialize class type but not the namespace to a Json string using DataContractJsonSerializer

I'm trying to serialize a class hierarchy to a Json string using DataContractJsonSerializer, in a WCF service.
the default behaviour for serializing a derived class is to add the following key value pair to the object:
"__type":"ClassName:#Namespace"
My problem is that namespaces are long and they bloat the Json string.
I would like to somehow intervene with the serialization and output this instead:
"__type":"ClassName"
and on deserialization intervene again to point to the correct namespace (which i know in runtime).
Is there any way to do such a thing?
This page describes the circumstances under which the __type property is emitted. In short, in WCF, if you use a derived type, and a KnownTypeAttribute, then you're going to get a __type property.
Example:
Assume
[DataContract]
[KnownType(typeof(Subscriber))]
public class Person { ... }
[DataContract]
public class Subscriber : Person { ... }
This code generates a __type property:
var o = new Subscriber("Fleming");
var serializer = new DataContractJsonSerializer(typeof(Person));
serializer.WriteObject(Console.OpenStandardOutput(), o);
But this code does not:
var o = new Subscriber("Fleming");
var serializer = new DataContractJsonSerializer(typeof(Subscriber));
serializer.WriteObject(Console.OpenStandardOutput(), o);
Notice that the second snip uses a DCJS with the same type as the object being serialized.
To avoid the __type, don't use derived types, or to be precise, use a serializer typed to the type you are actually serializing. If the serialization is being performed implicitly by a WCF method, then the method must be typed appropriately. In my example, it means you must use a return type of "Subscriber", and not the parent type, "Person".
The __type is emitted into the JSON stream by the (private) WriteServerTypeAttribute method on the
(internal) System.Runtime.Serialization.Json.XmlJsonWriter class. There is no public, documented, supported way to modify that, as far as I can tell.
To avoid this, you'd maybe need to return a string from the WCF method, perform the serialization yourself, and post-process the emitted JSON.
If you don't mind the __type thing, but just want to remove the qualifying namespace from the value, then put your types in the global namespace. In other words, put them outside of any namespace declaration in code.
Example: When the data types reside in a namespace, and when I used a derived type, the serialized JSON looks like this:
{
"__type":"Subscriber:#My.Custom.Namespace",
"Index":604455,
"Name":"Fleming",
"Id":580540
}
When the data types reside in the global namespace, it looks like this:
{
"__type":"Subscriber:#",
"Index":708759,
"Name":"Fleming",
"Id":675323
}
Adding the namespace parameter to the data contract does the trick.
[DataContract(Namespace = "")]
Cheeso's answer was excellent. I did discover a refinement to cleaning up the __type field though:
Rather than removing your subclass from its namespace you can add a property like the following:
[DataMember(Name = "__type")]
public string SubclassType
{
get
{
return "Subscriber";
}
set { }
}
You still get stuck with the ugly name "__type" but I found that because I was returning a list of subtypes I wanted to specify the type name anyway. You could even return a value of "" to further reduce response size. You could also just declare the property as:
public string __type
but I found that to accentuate the hack so I stuck with an appropriate property name and then renamed it.
-Joey
Note: I typed up this answer below and later realized that DataContractResolver is currently not supported with DataContractJsonSerializer. It may soon be with the next release of the framework, however. This is also useful if you are looking at more than just JSON.
**
You can do this with a DataContractResolver, which lets you map types to xsi:type (__type) information and vice-versa in a custom manner.
To do this, check out this blog post on DataContractResolver, plus this conceptual topic, plus this sample
#Cheeso wrote:
To avoid this, you'd maybe need to return a string from the WCF
method, perform the serialization yourself, and post-process the
emitted JSON.
Here's how I implemented that post-processing. I thought I'd post it here JIC it might help someone else.
First some boilerplate to show how I generate my JSON string:
// Instantiate & populate the object to be serialized to JSON
SomeClass xyz = new SomeClass();
... populate it ...
// Now serialize it
DataContractJsonSerializer ser = new DataContractJsonSerializer(xyz.GetType()); // Note xyz.GetType()
... serialize the object to json, many steps omitted here for brevity ...
string json = sr.ReadToEnd();
(Serialization is based on examples from https://msdn.microsoft.com/en-us/library/bb412179%28v=vs.110%29.aspx )
Note that the [DataContract] on SomeClass does not include the (name="") syntax that I've seen suggested elsewhere. That only removes the namespace from the __type at the cost of needing to adorn ALL your DataContract attrs, which clutters your code. Instead, my post-processor handles the assembly name in the __type field.
And now the string json contains the JSON text, but unfortunately includes all that "__type" junk that you don't want but can't suppress.
So here's my post-processing code that removes it:
// This strips out that unsuppressable __type clutter generated by the KnownType attributes
Attribute[] attrs = Attribute.GetCustomAttributes(xyz.GetType());
foreach (Attribute attr in attrs)
{
if (attr is KnownTypeAttribute)
{
KnownTypeAttribute a = (KnownTypeAttribute)attr;
string find = "\"__type\":\"" + a.Type.ReflectedType.Name + "." + a.Type.Name + ":#" + a.Type.Namespace + "\",";
json = json.Replace(find, "");
}
}
This makes a few assumptions, most notably that the __type field ends with a comma, which assumes that another field follows it, though (a) my objects always have at least 1 field and (b) I've found that the __type field is always 1st in the serialized object's output.
As always, you may have to adjust something to your situation, but I find it works well for mine.
Some times ago i decided this problem.
I use DataContractJsonSerializer
You will have __type in json, if your method for serialization have Base class parameter, but you give it subClass as parameter.
More details:
[DataContract]
[KnownType(typeof(B))]
public abstract class A
{
[DataMember]
public String S { get; set; }
}
[DataContract]
public class B : A
{
[DataMember]
public Int32 Age { get; set; }
}
public static String ToJson<T>(this T value)
{
var serializer = new DataContractJsonSerializer(typeof(T));
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, value);
return Encoding.UTF8.GetString(stream.ToArray());
}
}
You have two methods for test:
public static void ReadTypeDerived(A type)
{
Console.WriteLine(ToJson(type));
}
and
public static void ReadType<T>(T type)
{
Console.WriteLine(ToJson(type));
}
In first test you wiil have
"{\"__type\":\"B:#ConsoleApplication1\",\"S\":\"Vv\",\"Age\":10}"
In second:
"{\"S\":\"Vv\",\"Age\":10}"

EF4 Cast DynamicProxies to underlying object

I'm using Entity Framework 4 with POCO template.
I have a List where MyObject are dynamic proxies. I want to use the XmlSerializer to serialize this list, but I don't want them serialized as DynamicProxies but as the underlaying POCO object.
I know about ContextOptions.ProxyCreationEnabled, but I do not want to use that. I just want to know how to cast a proxy object to it's underlaying POCO to serialize.
Faced the same issue today and used Value Injecter to solve it. It's as simple as:
var dynamicProxyMember = _repository.FindOne<Member>(m=>m.Id = 1);
var member = new Member().InjectFrom(dynamicProxyMember) as Member;
Ill dig these old bones up by offering a solution that helped me. Hopefully, it will help someone that reads it.
So, there are actually two solutions. If you don't want lazy loading you can always turn off dynamic proxies and that will give you just the entitiy:
public class MyContext : DbContext
{
public MyContext()
{
this.Configuration.ProxyCreationEnabled = false
}
public DbSet<NiceCat> NiceCats {get; set;}
public DbSet<CrazyCat> CrazyCats {get; set;}
public DbSet<MeanCat> MeanCats {get; set;}
}
The other solution is to use the ObjectContext to get the original entity type the proxy stands in for:
using (var db = new MyContext())
{
var meanAssCat = context.MeanCats.Find(CurrentCat.Id)
var entityType = ObjectContext.GetObjectType(meanAssCat.GetType());
}
As you don't want to turn ProxyCreation off, you are stuck DynamicProxy objects wherever you put virtual keyword for object property (EF Context inherits your object and replaces virtual properties with DynamicProxy objects). These DynamicProxy objects do not inherit from your POCO entities, they just have same properties and can be used instead of your POCO. If you really must to convert to POCO object (and I don't believe that someone will come up with a way to cast it), you may try to workaround by writing copy constructor which will copy all properties from passed argument (not very smart from performance standpoint, but what you have to do, you have to do), or maybe using System.Xml.Serialization.XmlTypeAttribute in parent object which contains your dynamic proxy instead of poco to tell serializer how to serialize virtual property (into which type).
Disclaimer: I've created a somewhat generic solution to this problem. I found this old question while searching for a solution so I figured I'd share my solution here to help whoever may be stubbing his or her toe on the same problem.
I ran into the same problem: I needed to get some stuff from Entity Framework, and then use ASP.NET Web Api to serialize it to XML. I've tried disabling lazy loading and proxy creation and using Include(), but on anything but the most basic class hierarchy that led to gigantic SQL queries that took several minutes to execute. I found that using lazy loading and referencing each property recursively was many, many times faster than loading the tree all at once, so I figured I'd need a way to lazy load everything, get it in the form of a POCO, and then serialize it.
I've used this answer by Gert Arnold as the basis for this solution, and then worked from there.
I've created an Unproxy method in the DBContext that takes a (proxied) class instance (something you'd get back from DbContext.Find(id) for instance) and returns that entity as an actual POCO type, with each property, sub-property etc. fully loaded and ready for serialization.
The Unproxy method and some readonly fields:
readonly Type ignoreOnUnproxyAttributeType = typeof(IgnoreOnUnproxyAttribute);
readonly string genericCollectionTypeName = typeof(ICollection<>).Name;
public T UnProxy<T>(T proxyObject) where T : class
{
// Remember the proxyCreationEnabled value
var proxyCreationEnabled = Configuration.ProxyCreationEnabled;
try
{
Configuration.ProxyCreationEnabled = false;
T poco = Entry(proxyObject).CurrentValues.ToObject() as T; // Convert the proxy object to a POCO object. This only populates scalar values and such, so we have to load other properties separately.
// Iterate through all properties in the POCO type
foreach (var property in poco.GetType().GetProperties())
{
// To prevent cycles, like when a child instance refers to its parent and the parent refers to its child, we'll ignore any properties decorated with a custom IgnoreOnUnproxyAttribute.
if (Attribute.IsDefined(property, ignoreOnUnproxyAttributeType))
{
property.SetValue(poco, null);
continue;
}
dynamic proxyPropertyValue = property.GetValue(proxyObject); // Get the property's value from the proxy object
if (proxyPropertyValue != null)
{
// If the property is a collection, get each item in the collection and set the value of the property to a new collection containing those items.
if (property.PropertyType.IsGenericType && property.PropertyType.Name == genericCollectionTypeName)
{
SetCollectionPropertyOnPoco<T>(poco, property, proxyPropertyValue);
}
else
{
// If the property is not a collection, just set the value of the POCO object to the unproxied (if necessary) value of the proxy object's property.
if (proxyPropertyValue != null)
{
// If the type of the property is one of the types in your model, the value needs to be unproxied first. Otherwise, just set the value as is.
var unproxiedValue = (ModelTypeNames.Contains(property.PropertyType.Name)) ? SafeUnproxy(proxyPropertyValue) : proxyPropertyValue;
property.SetValue(poco, unproxiedValue);
}
}
}
}
return poco; // Return the unproxied object
}
finally
{
// Zet ProxyCreationEnabled weer terug naar de oorspronkelijke waarde.
Configuration.ProxyCreationEnabled = proxyCreationEnabled;
}
}
ModelTypeNames is a property I've added to my DBContext that simply returns all the types used in the model. That way we'll know which types we need to unproxy:
private Collection<string> modelTypeNames;
private Collection<string> ModelTypeNames
{
get
{
if (modelTypeNames == null)
{
// We'll figure out all the EF model types by simply returning all the type arguments of every DbSet<> property in the dbContext.
modelTypeNames = new Collection<string>(typeof(VerhaalLokaalDbContext).GetProperties().Where(d => d.PropertyType.Name == typeof(DbSet<>).Name).SelectMany(d => d.PropertyType.GenericTypeArguments).Select(t => t.Name).ToList());
}
return modelTypeNames;
}
}
To deal with ICollection<> properties, we need to first instantiate a new generic collection (I'm using reflection to create a HashSet<> with the right type argument), iterate through all the values, unproxy each value and add it to the new HashSet, which is then used as the value for the POCO's property.
private void SetCollectionPropertyOnPoco<T>(T poco, PropertyInfo property, dynamic proxyPropertyValue) where T : class
{
// Create a HashSet<> with the correct type
var genericTypeArguments = ((System.Type)(proxyPropertyValue.GetType())).GenericTypeArguments;
var hashSetType = typeof(System.Collections.Generic.HashSet<>).MakeGenericType(genericTypeArguments);
var hashSet = Activator.CreateInstance(hashSetType);
// Iterate through each item in the collection, unproxy it, and add it to the hashset.
foreach (var item in proxyPropertyValue)
{
object unproxiedValue = SafeUnproxy(item);
hashSetType.GetMethod("Add").Invoke(hashSet, new[] { unproxiedValue }); // Add the unproxied value to the new hashset
}
property.SetValue(poco, hashSet); // Set the new hashset as the poco property value.
}
Note that I'm calling SafeUnproxy rather than Unproxy. This is because of a weird issue with type inference. Usually when you pass a proxy object to Unproxy(), type inference will infer that T is the POCO type you actually want, not the type of the dataproxy (the one that looks like YourModelPocoType_D0339E043A5559D04303M3033 etc). However, occasionally it does infer T as the dataproxy type, which blows up the
T poco = Entry(proxyObject).CurrentValues.ToObject() as T;
line, because the poco object can't be cast to the proxy type, causing the as operator to return null. To fix this, SafeUnproxy calls the Unproxy method with an explicit type parameter rather than relying on inference: it checks the type of the parameter you pass it, and if the namespace is System.Data.Entity.DynamicProxies, it'll use the type's BaseType (which in the case of a dynamicproxy type is the corresponding POCO type) as the generic type argument.
private object SafeUnproxy(dynamic item)
{
// ProxyCreation is off, so any reference or collection properties may not yet be loaded. We need to make sure we explicitly load each property from the db first.
ExplicitlyLoadMembers(item);
// Figure out the right type to use as the explicit generic type argument
var itemType = item.GetType();
Type requiredPocoType = (itemType.Namespace == "System.Data.Entity.DynamicProxies") ?
itemType.BaseType :
itemType;
// Call Unproxy using an explicit generic type argument
var unproxiedValue = typeof(VerhaalLokaalDbContext).GetMethod("UnProxy").MakeGenericMethod(requiredPocoType).Invoke(this, new[] { item });
return unproxiedValue;
}
Making sure each property is loaded from the database is a matter of iterating through the properties of the object and checking IsLoaded:
private void ExplicitlyLoadMembers(dynamic item)
{
foreach (var property in ((Type)item.GetType()).GetProperties())
{
DbEntityEntry dbEntityEntry = Entry(item);
var dbMemberEntry = dbEntityEntry.Member(property.Name);
// If we're dealing with a Reference or Collection entity, explicitly load the properties if necessary.
if (dbMemberEntry is DbReferenceEntry)
{
if (!dbEntityEntry.Reference(property.Name).IsLoaded)
{
dbEntityEntry.Reference(property.Name).Load();
}
}
else if (dbMemberEntry is DbCollectionEntry)
{
if (!dbEntityEntry.Collection(property.Name).IsLoaded)
{
dbEntityEntry.Collection(property.Name).Load();
}
}
}
}
Finally, the IgnoreOnUnproxyAttribute used to avoid cycles:
[System.AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
sealed class IgnoreOnUnproxyAttribute : Attribute
{
}
Usage is as follows:
MyDbContext db = new MyDbContext();
public Story Get(int storyId)
{
var lazyStory = db.Stories.SingleOrDefault(s => s.Id == storyId);
var unproxied = db.UnProxy(lazyStory);
return unproxied;
}
Performance isn't spectacular due to all the reflection going on, but execution time is on average only slightly (i.e. less than a second) longer than when lazy loading an entity, iterating through all its properties, and then serializing the dynamicproxy itself. Also, it's much, much faster than when using Include() which is dreadfully slow and error-prone.
Hope it helps somebody.
I faced with the same issue in EF 5. I was trying to serialize my entity objects to XML. #Koreyam s answer gave me a hint. I developed it little bit more.
Somewhere in my code i was calling the serializer like this
string objXML = EntitySerializer.Serialize(entity);
Serialize method is generic. So method header is like this :
public static string Serialize<T>(T tObj) where T : class, new()
So in my method body i use value injecter :
T obj = new T().InjectFrom(tObj) as T;
it just solved my issue for all of my entitites.

Categories

Resources