Custom annotation processing while coding - annotations

The purpose of the project I'm working on is to handle annotation at compile time, it is not focused on what exactly I'm developing.
I took a simple subject for this and I'm writing a custom collection that will store elements and provide methods to manage them.
What I wanna do is to create an annotation #Contains, for example, to generate itemsContains method that could be processed while coding (instead of writing code manually).
public class Array {
private List<String> items;
public Array() {
items = Arrays.asList("abc", "def", "xyz");
}
public boolean itemsContains(String expected) {
return items.contains(expected);
}
}
Generally, I want my class to look something like:
public class Array {
#Contains
private List<String> items;
public Array() {
items = Arrays.asList("abc", "def", "111");
}
}
The important thing I want to reach is to have itemsContains method show up once the annotation is applied to a field. This is how it should look like:
expected result
Alternate existing examples are Lombok's #Getter/#Setter.
So what functionality or configurations should I implement to get the expected result?
Would be grateful for some real implementations or guides how to perform it step by step.

Annotation processing does not change the source file yet it generates a new file,
Lombok on the other hand does a trick to modify the source file itself, meaning that you need to call the generated class somewhere in your code.
One way to do this is to generate a class that extends the main class
#Generated
public class ArrayProxy extends Array {
public boolean itemsContains(String expected) {
return items.contains(expected);
}
}
and in your main class you need to do two things:
first you need to make items protected
you can add factory method to actually create the generated class
public class Array {
#Contains
protected List<String> items;
public static ArrayProxy create(){
return new ArrayProxy();
}
private Array() {
items = Arrays.asList("abc", "def", "111");
}
}
And of course you need to use it like this
ArrayProxy array = Array.create();
array.itemsContains("expected");

Related

Define Generic List from interface

This may be an easy answer, but I'm creating what I thought was a simple interface that is to contain a definition for a generic list. Basically just something that says "create a generic list" like below:
public static List<UserControl> ViewList = new List<UserControl>();
This is proving more difficult than I expected. Maybe I'm going about it wrong? Each definition I try results in the expected list being a property or a method. For example, I've tried the below with no luck
//FirstTry
public interface IAddToViewList
{
List<UserControl> ViewList();
}
//Second
public interface IAddToViewList
{
List<UserControl> ViewList { get; set; }
}
Also I'm not sure if it's possible to include that the list should be static, I'm having trouble finding anyone with a question matching these requirements, maybe because it's just not possible or I'm thinking about it the wrong way?
Interfaces are collections of abstract methods. This means that you are unable to add class variables to them.
What you would need to functionally accomplish this is an Abstract Class.
public abstract class AddToViewList
{
List<UserControl> ViewList;
}
However, all you need to do is define a method that returns a list
public interface IAddToViewList
{
public List<UserControl> createViewList();
}
This will ensure that every class that implements IAddToViewList also has the createViewList() method. Now, in this case, UserControl would have to be a defined class and so this is a list of UserControl objects, not a "Generic List".
To make the list generic you have add the diamond after the interface name:
public interface IAddToViewList<UserControl>
{
public List<UserControl> createViewList();
}
then when you are implementing your class it would look like this
public class Foo implements IAddToViewList<String>
{
public List<String> createViewList(){
// TODO
return null;
}
}

Getting JSON Serialization Entity Framework Self Reference Loop error even after ProxyCreation false when using explicit Include

JSON Serialization (ASP.Net Web API) fails because of self-referencing loop (it’s a common problem, Reason: an entity being requested lazy loads child entities and every child has a back reference to parent entity).
Work around I found, but doesn’t help me:
Use [JsonIgnore] for navigation properties to be ignored:
This solution works but doesn’t apply in my case. For Example: To get a Customer information along with his Orders, I would quickly add [JsonIgnore] to Customer property in Order class, but when I want to get an Order information along with the Customer details, since there’s [JsonIgnore] on Customer property, it won’t include Customer details.
Change JSON.Net Serializer Settings to Preserve References:
Can’t Preserve because I don’t need Circular referenced data.
Disable Proxy Creation at the Data Context and use explicit loading(this should ideally solve the problem):
Disabling proxy creation stops Lazy Loading and returns data without error, but when I explicitly Include child entities, I again the get the unexpected self-referencing loop error! The error is at the back-reference level to parent entity.
Any experiences along the same lines/suggestions?
I tried all the suggested solutions but didn't work. Ended up with Overriding the JSON.Net Serializer’s DefaultContractResolver to this:
public class FilterContractResolver : DefaultContractResolver
{
Dictionary<Type, List<string>> _propertiesToIgnore;
public FilterContractResolver(Dictionary<Type, List<string>> propertiesToIgnore)
{
_propertiesToIgnore = propertiesToIgnore;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
List<string> toIgnore;
property.Ignored |= ((_propertiesToIgnore.TryGetValue(member.DeclaringType, out toIgnore) || _propertiesToIgnore.TryGetValue(member.DeclaringType.BaseType, out toIgnore)) && toIgnore.Contains(property.PropertyName));
return property;
}
}
Then created a Static Class which returns a dictionary of Properties to be Ignored based on the Controller:
public static class CriteriaDefination
{
private static Dictionary<string, Dictionary<Type, List<string>>> ToIgnore = new Dictionary<string, Dictionary<Type, List<string>>>
{
{
"tblCustomer", new Dictionary<Type, List<string>>{
{
typeof(tblCustomer), new List<string>{
//include all
}
},
{
typeof(tblOrder), new List<string>{
"tblCustomer"//ignore back reference to tblCustomer
}
}
}
},
{
"tblOrder", new Dictionary<Type, List<string>>{
{
typeof(tblCustomer), new List<string>{
"tblOrders"//ignore back reference to tblOrders
}
},
{
typeof(tblOrder), new List<string>{
//include all
}
}
}
}
};
public static Dictionary<Type, List<string>> IgnoreList(string key)
{
return ToIgnore[key];
}
}
And inside every controller change the JSON Formatter something like:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new FilterContractResolver(CriteriaDefination.IgnoreList("tblCustomer"));
This is what I ended up settling on, hopefully it helps someone else.
Say the EF classes are structured like this:
public partial class MyEF
{
public virtual ICollection<MyOtherEF> MyOtherEFs {get; set;}
}
public partial class MyOtherEF
{
public virtual MyEF MyEF {get; set;}
}
To keep serialization form happening in JSON.NET, you can extend the class and add a method with the name "ShouldSerialize" + property name like so:
public partial class MyEF
{
public bool ShouldSerializeMyOtherEFs() { return false; }
}
If you wanted to get a little more fancy, you could add logic in the method so that it would serialize in certain cases. This allows you to keep serialization logic out of the EF Model First code creation as long as this code is in a different physical code file.
Instead of letting the Entity Framework generate the model, use Code First with an existing database. Now you are more in control.
See this blog entry from Scott Guthrie

EF: Many tables with the same column - can I access to it without copying the code?

I have some tables which stores the file's data, e.g TabA, TabB, TabC, ... TabX. Each of them has the same column FileTypeID.
For each table I need to use the extension method to get the rows depending of the condition of the FileTypeID column. To do so, I have an extension method like that:
public static class FilesTab_Extenders
{
public static IList<TabA> GetSpecificFiles(this EntityCollection<TabA> mc)
{
///
}
}
but, I don't want mindlessly clone the same code for the rest of tables. The only difference will be the parameter - this EntityCollection<TabB>, this EntityCollection<TabC> etc. So, is it somehow possible to make the universal code for that scenario ?
To me the easiest way to do this would be to use an interface. You would then have your partial classes implement this interface and use it in your extention method:
public interface IFileTypeable
{
Guid FileTypeId { get; set;}
}
Now you would create partial class files for each of your TabA, TabB, TabC, ... TabX that follow this template:
namespace MyDBContextNamespace
{
public partial class TabA : IFileTypeable
{
// no need to do anything, the property is already implemented on the original class file.
}
public partial class TabB : IFileTypeable
{
// no need to do anything, the property is already implemented on the original class file.
}
}
Finally your extention method would be changed to look like this:
public static IList<IFileTypeable> GetSpecificFiles(this EntityCollection<IFileTypeable> mc)
{
foreach (var item in mc)
{
Guid fileTypeId = item.FileTypeId;
}
}

Persist derived objects using Mongo C# driver

I have the following class hierarchy
[BsonKnownTypes(typeof(MoveCommand))]
public abstract class Command : ICommand
{
public abstract string Name
{
get;
}
public abstract ICommandResult Execute();
}
public class MoveCommand : Command
{
public MoveCommand()
{
this.Id = ObjectId.GenerateNewId().ToString();
}
[BsonId]
public string Id { get; set; }
public override string Name
{
get { return "Move Command"; }
}
public override ICommandResult Execute()
{
return new CommandResult { Status = ExecutionStatus.InProgress };
}
}
if I save the command like so:
Command c = new MoveCommand();
MongoDataBaseInstance.GetCollection<Command>("Commands").Save(c);
and then query the DB, I don't see the derived properties persisted.
{ "_id" : "4df43312c4c2ac12a8f987e4", "_t" : "MoveCommand" }
I would expect a Name property as a key in the document.
What am I doing wrong?
Also, is there a way to avoid having a BsonKnowTypes attribute on the base class for persisting derived instances? I don't see the why a base class needs to know about derived classes. This is bad OO design and is being forced on my class hierarchy by the BSON library. Am I missing something here?
1.Name property was not saved into database because it haven't setter. Serializers not serialize properties that's haven't setters (because if serializer serialize such property it will not able deserialize it back). So if you want serialize Name property then just add fake setter(into ICommand need to add it also):
public override string Name
{
get { return "Move Command"; }
set{}
}
2.If you don't want use BsonKnownTypes attribute there is another way to notify serializer about know types it might encounter during deserialization. Just Register maps once, on app start event:
BsonClassMap.RegisterClassMap<MoveCommand>();
//all other inherited from ICommand classes need register here also
So you should use or KnownTypes attribute or register BsonClassMap for each polymorphic class, otherwise you will get 'unknown descriminator' error during deserializtion:
var commands = col.FindAllAs<ICommand>().ToList();
3 You said:
This is bad OO design and is being
forced on my class hierarchy by the
BSON library.
In any way even without KnownTypes atribute your code using Bson lib through BsonId attribute.
If you want avoid it you can:
BsonClassMap.RegisterClassMap<MoveCommand>(cm => {
cm.AutoMap();
cm.SetIdMember(cm.GetMemberMap(c => c.Id));
});
So now you can remove reference to Mongodb.Bson lib from your domain code lib.

Retrieve values from a config file into a class, in C#?

Using C#. how would one get values from a config file into a class? I guess you can pass a key and it will get the value based on that.
I know you can use
string value = ConfigurationManager.AppSettings["test"];
But I thought there might be a better way, maybe using it in a class?
Is this OK?
public static string GetKey(string value)
{
get
{
return ConfigurationSettingAppSetting[value];
}
}
and to use it I use
GetKey("test");
Is this good or good pratice using it as a static?
thanks
I prefer not to use strings to get values out of the configuration. Instead I create
public static class Config
{
public static string Test
{
get { return ConfigurationManager.AppSettings["Test"]; }
}
}
also allowing for strong typing
public static class Config
{
public static int ApplicationId
{
get { return int.Parse(ConfigurationManager.AppSettings["ApplicationId"]); }
}
}
This creates a simple abstraction without going all out and creating configuration sections.