I wanna generate C# protobuf code with customize attributes.
such as:
public sealed partial class LoginIn : pb::IMessage<LoginIn>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
[mycall] // customize attributes
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] // original
public LoginIn() {
OnConstruction();
}
... // rest code
With partial class, you can add attributes (and members) to the type, but you can't add attributes to individual members, so: you can't do anything simple here. Effectively, you'd need to tweak the code-gen itself (meaning: create your own version of the protoc addin), which is far from ideal.
The other option is manually editing the generated code - again: far from ideal.
Before doing either of those, I'd have to ask myself some serious questions about [mycall] and how important it is, what it does, and whether adding it to the serialization model is necessary, vs creating my own domain model that can have any attributes you want, and mapping between the domain model and the serialization model.
Related
My problem is similar to this one, except that the code I want to use with protobuf-net was generated by the WSDL utility. "They tell me" that it's not appropriate to plan to modify the generated code (to add attributes).
It would be odd to write something to build a matching set of DTO classes, given that (other than the methods described) all the classes are already public (partial) classes marked with [Serializable] and have all public properties -- that is, they are very DTO-like already.
The simplest solution I've seen is to violate the rules and modify the code. If all strings in the generated C# file
public partial class
are replaced with
[ProtoBuf.ProtoContract(ImplicitFields = ProtoBuf.ImplicitFields.AllPublic)]
public partial class
from my limited testing that will do the trick. Does a better solution exist? Is there something wrong with using that technique (other than that I'm modifying generated code)?
Type-level attributes in partial classes can be added in separate code files. All you need is a separate file with just:
[ProtoBuf.ProtoContract(ImplicitFields = ProtoBuf.ImplicitFields.AllPublic)]
public partial class {}
it must also be in the right namespace, but you didn't say which, so probably:
namespace Foo {
[ProtoBuf.ProtoContract(ImplicitFields = ProtoBuf.ImplicitFields.AllPublic)]
public partial class {}
}
I'm basically re-asking this question as the only and accepted answer is not an answer to the question.
Is it possible to tell EF to use a class that subclasses EntityObject, like the one below, as the base class of generated entity classes?
public abstract class CustomEntityObject : EntityObject
{
<additional functionality>
}
The reason I'm asking is I want to stop adding interfaces and implementing them on all entity types in separate partial class files. By sub-classing EntityObject I could implement the additional functionality once only.
Update:
EF implicitly uses a .tt file to generate entity classes. By implicitly I mean you don't see the .tt file in your project. The solution is to add the template explictly (right-click on the .edmx designer and click "Add Code Generation Item...", then add "ADO.NET EntityObject Generator"). You then change a single value in the .tt:
string BaseTypeName(EntityType entity, CodeGenerationTools code)
{
return entity.BaseType == null ? "EntityObject" : MultiSchemaEscape((StructuralType)entity.BaseType, code);
}
changes to:
string BaseTypeName(EntityType entity, CodeGenerationTools code)
{
return entity.BaseType == null ? "CustomEntityObject" : MultiSchemaEscape((StructuralType)entity.BaseType, code);
}
You can use such hack (this is hack).
Create class "abstract class EntityObject : System.Data.Objects.DataClasses.EntityObject" in the same namespace with your entities. Then you can use this class as base class.
But if you want to create complex and beauty solution - use T4 templates, custom generation etc. You can find solutions here, here.
Thing is, that using default T4 template designer will generate entity classes inherited from EntityClass.
To use model designer and have ability to supply custom base class you need to download http://msdn.microsoft.com/en-us/library/ff477605.aspx (it's a description how to use it, before it was in add item>online templates, but at least on my vs2012 can't find it anymore, it tmay be that is gone for a reason) template and edit template files to inject your custom base class, but I think that most of programmers look at POCO for a reason, so may be better idea is to have classes that don't have persistence attached.
I used the OWLGrinder to create the assembly and imported the library into my project. That works fine. Now I want to write my own set of classes. Therefore I extended these with the equivalent of the assembly. But it just doesn't work.
The ontology holds a class named ManagementObject.
I created another Class (C#) called RealWorldObject:
public class RealWorldObject : ManagementObject
{
public RealWorldObject(string uri) : base(uri) { }
public RealWorldObject(string uri, RdfDocument rdfdocument) : base(uri, rdfdocument) { }
public RealWorldObject(RdfDocument rdfdocument) : base(rdfdocument) { }
public String getClassName()
{
return this.OwlClassName;
}
public static RdfDocument addRealWorldObjectIndividualt(RdfDocument rdfDocument)
{
Vehicle vehicle = new Vehicle("vehicle1", rdfDocument);
FixedEvent fxE1 = new FixedEvent("autoGekauft", rdfDocument);
fxE1.agent = new xmlns.com.foaf._01.Person("robert", rdfDocument);
vehicle.hasFixedEvent = fxE1;
return rdfDocument;
}
Which leads to the error:
ObjectManagement.Object.RealWorldObject does declare one (and only one) OwlClassAttribute. This is an implementation bug of the plugin.
How else should I extend the generated classes by the OWLGrinder.
Thx it is a long time ago that I used C#, so I'm kind of rusty.
The auto-generated classes produced by OwlGrinder.exe have not been designed for inheritance in mind. I am not saying it is wrong, it is just not designed for that. The auto-generated classes contain plenty of metadata defined as class attributes and inheritance hides all of that. The infrastructure counts on the presence of these attributes and if they are hidden, you get these runtime error messages.
Using Visual Studio Object Browser, take a look of the attributes over the auto-generated classes. OwlClassAttribute, SubClassOfAttribute, LightVersionAttribute are certainly mandatory. You may simply copy/paste the class attributes of ManagementObject on the top of your RealWorldObject class. I assume, it will work. But again, you might bump into additional show stoppers, as you do not follow the default routes ROWLEX has been designed for. This is a bit living on the edge :)
Instead of inheritance, you might consider reverse engineering your auto-generated assembly to C# using Reflector or other tools. Having the source code in your hand, you may modify the generated classes directly. You might make your ManagementObject class partial, and implement your additional methods in a separate file.
I've been using SubSonic 2 for a while now, but as I am starting a new project, I'd like to upgrade to 3. In my old project, I used a custom, non-sustainable hack to serialize things for web services. I really would like to find a more elegant solution.
I'm using Mono, so I need to stay within implemented classes, e.g. DataContractSerializer is probably out. Still on ASMX, though would love to upgrade to WCF as soon as the support is solid. Moonlight/Silverlight will be the initial clients. JSON/protobuf in the future...
The standard Xml serializer is opt-out, so I'd need some way to take control of it. Which brings me to IXmlSerializable. I'm rather unfamiliar with SS's templates, but it seems that editing these would allow me to generate the serialization code necessary to not touch the rest of the hierarchy chain. Is this a "good idea"?
I'd love to just use SS's POCO support, but I don't think it supports complex types or arrays.
Other thoughts/options?
IXmlSerializable is IMO more than a little awkward to get right. Note that if you are handling the XmlSerializer code yourself you can override everything at runtime by using the constructor that accepts XmlAttributeOverrides (but if you use this you should cache and re-use the XmlSerializer instance, or it will leak like a sieve).
You briefly mention protobuf; note that protobuf-net (even in v1) allows you to add member-level serialization data at the type level, so you can include that information in a partial class alongside a generated type:
// file 1
partial class GeneratedClass
{
public int Foo { get; set; }
public string Bar { get; set; }
}
// file 2
[ProtoPartialMember(1, "Foo")]
[ProtoPartialIgnore("Bar")]
partial class GeneratedClass {}
So a little confession, I've never written an attribute class. I understand they serve the purpose of decorating classes with flags or extra functionality possibly.
Can someone give me a quick example of not just creating and applying an attribute to a class, but rather utilizing the attribute from another block of code. The only code samples I've ever seen to utilize any form of attributes was doing so with reflection, though I've always hoped there's a way of using them without reflection.
Attributes are always used with reflection. They are baked into the metadata of the types during compile time and the only way to read them is through reflection. Attributes are used when you want write a type and you want to associate some metadata with it which could be used by consumers of this type.
The simplest and most elegant way to use an attribute from another block of code is to use a property instead of an attribute.
See http://blogs.msdn.com/b/ericlippert/archive/2009/02/02/properties-vs-attributes.aspx for a discussion of the differences between properties and attributes.
First create your attribute
public class ImportableAttribute : Attribute
{
}
Then a class with a item that uses the Attribute
[ImportableAttribute]
public class ImportClass
{
[ImportableAttribute]
public string Item {get; set;}
}
Then check if that property uses that attribute. Can be done with classes to.. Of course :)
PropertyInfo property = typeof(ImportClass).GetProperty("Item");
if (property.IsDefined(typeof(ImportableAttribute),true))
{
// do something
}
With a class:
typeof(ImportClass).IsDefined(typeof(ImportableAttribute), true);