LINQ ToList() serialization error? - c#

I have a LINQ -> Class file named MoviesDB.dbml, I have added one table "Movie" to it, i have created a class "Movies" in which i have implemented inside all the methods.
Method GetAllMovies which gets a List, when binding the list i get the following:
Type 'DyMvWebsite.Movie' in Assembly 'DyMvWebsite, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
The code for the Method:
public static List<Movie> GetAllMovies()
{
List<Movie> oMoviesList = new List<Movie>();
using (MoviesDBDataContext oMoviesDBDataContext = new MoviesDBDataContext())
{
oMoviesList = oMoviesList.ToList<Movie>(); ;
}
return oMoviesList;
}
After that i have tried putting the [Serializable] attribute in the "Movies" class and tried putting it in the linq designer file too, but same problem.
Edit:
After following what 'Massimiliano Peluso' suggested, i received a new error:
Type 'System.Data.Linq.ChangeTracker+StandardChangeTracker' in Assembly 'System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.

Try this out
MoviesDBDataContext.ObjectTrackingEnabled = false;
before firing the query.
If this still fails, then the work around will be create serializable class similar to Movie class, and map the properties.

Everything contained in the Movie class must be Serializable as well
Apply the SerializableAttribute attribute to a type to indicate that instances of this type can be serialized. The common language runtime throws SerializationException if any type in the graph of objects being serialized does not have the SerializableAttribute attribute applied.
Apply the SerializableAttribute attribute even if the class also implements the ISerializable interface to control the serialization process.
All the public and private fields in a type that are marked by the SerializableAttribute are serialized by default, unless the type implements the ISerializable interface to override the serialization process. The default serialization process excludes fields that are marked with the NonSerializedAttribute attribute. If a field of a serializable type contains a pointer, a handle, or some other data structure that is specific to a particular environment, and cannot be meaningfully reconstituted in a different environment, then you might want to apply the NonSerializedAttribute attribute to that field.
more info:
http://msdn.microsoft.com/en-us/library/system.serializableattribute(v=VS.100).aspx

Related

Cannot read CustomAttributes in assembly using reflection

I am having problems reading the CustomAttributes of one type.
TypeInfo mytype = ...
IEnumerable<CustomAttributeData> customAttributes = null;
try
{
customAttributes = mytype.CustomAttributes; // Or GetCustomAttributesData
} catch (TypeLoadException e)
{
// Could not access the attributes
throw new Exception("Type not loaded for the attribute", e);
}
The error I get in TypeLoadException e is:
Could not load type
'System.Runtime.CompilerServices.ScriptNamespaceAttribute' from
assembly 'mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.
The point is that e.TypeName has the name of the attribute class that I am using for that type, so the name is actually available!
Assembly loaded in reflection only context
I have loaded the assembly by using:
Assembly.ReflectionOnlyLoadFrom("Path to my assembly")
So I was expecting to be able to access types and read at least their names. It happens with classes and other types, but for custom attributes I have this problem. But if I open the ILDASM (the .NET Disassembler on my assembly). I can see ScriptNamespaceAttribute being applied to some of the classes defined in the assemblies.
The trick around custom attributes
In MSDN GetCustomAtrributesData I can see this:
Use this method to examine the custom attributes of code in the reflection-only context, in cases where the custom attributes themselves are defined in code that is loaded into the reflection-only context. Methods like Attribute.GetCustomAttributes and MemberInfo.GetCustomAttributes cannot be used in such cases, because they create instances of the attributes.
Does it basically mean I have no way to just read the names of these custom attributes? I don't want anything more than that, I just need to know the names of the custom attributes...
Question
How can I safely read the custom attributes in an assembly which references types defined externally? I do not need to have the implementation for these classes, just their names is what I need.

Can't clone object. Serialization issue

I have a class generated by Linq2Sql:
public partial class BuyerOrder : INotifyPropertyChanging, INotifyPropertyChanged
I want to clone object of this class, like it's done in this post. For this purpose I define the partial class in not generated file, which I mark as serializable:
[Serializable]
public partial class BuyerOrder
But when I'm calling
formatter.Serialize(stream, source);
I'm getting an exception, saying that this class is not marked as serializable. What am I doing wrong?
If you want to serialize a LINQ-to-SQL type, then tell the code-gen to emit serializable data. You can do this in the DBML, or more simply in the designer - just set the serialization mode to unidirectional (this is the #Serialization attribute on the root <Database> element in the DBML).
This will generate attribute markers suitable for use with DataContractSerializer; LINQ-to-SQL is designed to be serializable with DataContractSerializer. It is not designed to be serializable with BinaryFormatter.
Every class derived from BuyerOrder must also be decorated as [Serializable], as well as all objects that the serializing instance holds a reference to (unless decorated as NonSerializable).
The exception should tell you the type that is missing the serializable attribute. If you can not or do not want to decorate all the classes you will need to get a little more creative.
-- The other possibility --
One option is to use the technique described in Implementing a generic deep-clone for C# objects. Since this can be done entirely in memory and without a binary formatter it will perform many times faster than serialization based cloning.
The source code is located at http://csharptest.net/browse/src/Library/Cloning
It only takes two lines of code:
using (ObjectCloner cloner = new SerializerClone())
fooCopy = cloner.Clone(foo);

XML serialization related problem with XmlIgnore

When serializing a class I get an error if the XmlIgnore attribute is commented. When I uncomment the XmlIgnore attribute it works fine. Can anyone tell me why a property can't be serializable?
Normally, it will tell you why very clearly in the exception - look in particular at the InnerException; however, to summarise:
For a custom type SomeType to be serializable via XmlSerializer (either as the root object or via a property, i.e. public SomeType MemberName {get;set;})
it must be public
it must have a public parameterless constructor
a few generic combinations may not be supported
it must be expected (exposing data as object is a no-go, for example; subtypes of SomeType must be advertised in advance, typically via [XmlInclude(...)])
it must be concrete (non-abstract), or have concrete implementations defined via [XmlInclude(...)]
Using [XmlIgnore] removes the type from consideration, so types that are not xml-friendly can be avoided. You can also try IXmlSerializable for those cases

Is there a difference between name decoration/mangling and attribute decoration?

I've been reading a text about an extension to C# and at one point it says that "An attribute decoration X may only be applied to fields of type Y."
I haven't been able to find a definition for attribute decoration, and I'm not making much sense out of this by exchanging the two.
It's probably referring to the Attribute class. For example, you can mark a type as serializable via the SerializableAttribute. When you apply an attribute, you can leave off the "Attribute" suffix.
[Serializable]
public class SomeClass {
}
Attributes provide a means to add meta-data about the code.
Attributes are used to add metadata to .NET (C#) code in a structured manner. What a lot of people don't realise, though, is that there are actually two types of attribute.
The simplest is custom attributes, where you define an attribute that specific classes look for to alter the way they work. A common example is the System.Xml.Serialization attributes which are read by the XmlSerializer to alter its output, e.g. a class could be marked up something like the following to specify its namespace and that the field should be an attribute:
[XmlType(Namespace = "http://mycompany.com/")]
public class MyClass
{
[XmlAttribute]
public string MyField;
}
Custom attributes like this have no meaning to the compiler or the runtime, they are just added to the class as part of its metadata, and can be retrieved by a call to Type.GetCustomAttributes.
The other main group of attributes is pseudo-custom attributes, which actually have meaning to either the compiler or the runtime. The example in the post by Haacked with SerializableAttribute is actually an example of a pseudo-custom attribute. It is actually stored as part of the type definition and cannot be retrieved using Type.GetCustomAttributes. You cannot create your own pseudo-custom attributes.
So it's likely what you're dealing with here is a custom attribute which is being looked for by a specific tool.

Create an object knowing only the class name?

I have a set of classes, each one is a different strategy to do the same work.
namespace BigCorp.SuperApp
{
public class BaseClass { }
public class ClassA : BaseClass { }
public class ClassB : BaseClass { }
}
The choice of which strategy to use is configurable. I want to configure only the class name 'ClassB' instead of the full type name 'BigCorp.SuperApp.ClassB' in the app.config file.
<appConfig>
<SuperAppConfig>
<Handler name="ClassB" />
</SuperAppConfig>
</appConfig>
However, the reflection calls fail because they expect the full type name, particularly
Type t = Type.GetType("ClassB"); // results in t == null
BaseClass c = Activator.CreateInstance(t) as BaseClass; // fails
How can I get this to work while configuring only the class name? Concatenate the namespace to the class name for full type name? Is there another reflection call that works?
If you think this is useless and I should expect the configuration to contain the full type name, I am open to that solution! Just provide rationale to convince me.
(I will not be loading a type from outside this assembly/namespace)
Either use the assembly-qualified-name, or get hold of the Assembly and use Assembly.GetType(name). In this case, since you want the types in the config file, assembly-qualified is a valid way to go - but since you know all your types are in the same assembly:
Assembly assembly = typeof(SomeKnownType).Assembly; // in the same assembly!
Type type = assembly.GetType(name); // full name - i.e. with namespace (perhaps concatenate)
object obj = Activator.CreateInstance(type);
The static Type.GetType(string) has probing rules that often cause confusion... it looks at the calling assembly, and a few system assemblies - but not all loaded assemblies.
Since you know all classes will be coming from the same namespace, configure it once and use that:
<appConfig>
<SuperAppConfig handlerNamespace="BigCorp.SuperApp">
<Handler class="ClassB" />
</SuperAppConfig>
</appConfig>
Edit: I changed name to class to better denote the meaning of that attribute.
(I will not be loading a type from outside this assembly/namespace)
because of the above line, it is safe to assume that you know what the namespace is. Couldn't you do something like:
Type t = Type.GetType("Namespace." + className);
BaseClass c = Activator.CreateInstance(t) as BaseClass;
If you expect to possibly be able to add additional strategy classes to be loaded in the future, perhaps via an additional assembly, you would need to fully qualify your class name. This is recommended anyway, since you would be able to provide enhanced extendability for your application.
I'm going with the full type name in the application configuration. Below is a slightly more complete, but still trivial example
<SuperAppConfig>
<ObjectConfig provider="BigCorp.SuperApp.ClassA">
<add name="one" />
<add name="two" />
</ObjectConfig>
</SuperAppConfig>
And the factory class that actually creates this
private static Assembly a = typeof(IFactoryObject).Assembly;
public static IFactoryObject CreateObject(String providerName)
{
Type t = a.GetType(providerName)
IFactoryObject o = Activator.CreateInstance(t) as IFactoryObject;
return o;
}
BaseClass c = Activator.CreateInstance(t) as BaseClass; // fails
Might also result from the fact, that CreateInstance does not return an instance of BaseClass, rather than an instance of BaseClass wrapped into an ObjectHandle.
Cast into your BaseClass after you used the UnWrap method.

Categories

Resources