App Settings using Castle Dictionary Adapter - adding behavior at runtime - c#

I'm using the dictionary adapter as described in this blog post:
http://kozmic.net/2013/11/21/on-strongly-typed-application-settings-with-castle-dictionaryadapter/
for getting app setting dependencies.
I have 2 attributes defined:
AppSettingsFromConfigAttribute - for holding a keyprefix
AppSettingsBehavior : KeyPrefixAttribute, IDictionaryPropertyGetter, IPropertyDescriptorInitializer
which is a carbon copy of the AppSettingsAttribute attribute class in the blog post.
This is the registration:
Configure(component => component.UsingFactoryMethod(
() =>
{
var attrib = (AppSettingsFromConfigAttribute)Attribute.GetCustomAttribute(component.Implementation, typeof(AppSettingsFromConfigAttribute));
var prop = new PropertyDescriptor();
prop.AddBehavior(new AppSettingsBehavior(attrib.KeyPrefix));
return configFactory.GetAdapter(component.Implementation, new NameValueCollectionAdapter(ConfigurationManager.AppSettings), prop);
})));
So i use my custom attribute to avoid dependencies to Castle.Core throughout my codebase, but try and add the same behavior at runtime through the registration. This is working, the keyprefix part - but not the fetch part. This fails only on first use, not on construction.
If i use the AppSettingsBehavior statically on the interface, it works correctly, fetches and fails on construction. So where am i going wrong in adding behavior to the dictionary adapter?

After a few hours of looking at the source, scratching my head and a coffee. Found a solution :)
Basically in the addbehavior call i get to add dictionary behaviors, while what i need is an interface / property behavior to trigger (pre)fetch. In the source, the guys are checking for attributes on the supplied type all over the place, despite what the method signatures may say - but only taking dictionary initializers from the prop descriptor object, nothing for the interface / properties. Hence, even though the behavior i was adding had the interface behavior - it never got read, only the dictionary behaviors.
So, i use a different call. Instead of calling factory.GetAdapter - i instead get factory.GetAdapterMeta() - which gives me a meta object with a nice Properties getter - which has the collection for the actual interface properties.
So the code becomes:
Configure(component => component.UsingFactoryMethod(
() =>
{
var attrib = (AppSettingsFromConfigAttribute)Attribute.GetCustomAttribute(component.Implementation, typeof(AppSettingsFromConfigAttribute));
var prop = new PropertyDescriptor();
prop.AddBehavior(new AppSettingsBehavior(attrib.KeyPrefix));
var meta = configFactory.GetAdapterMeta(component.Implementation);
foreach (var entry in meta.Properties)
{
entry.Value.Fetch = true;
}
return meta.CreateInstance(new NameValueCollectionAdapter(ConfigurationManager.AppSettings), prop);
})));

Related

Can I write tests for custom attributes without defining x^n classes?

I'm building a class library that includes several custom attributes that apply to properties. Then I have methods that do certain things based on the placement of the attributes.
Now I want to build some unit tests, but how to I make the tests without creating something on the order of x^(number of attributes) classes just for testing purposes? Can I leverage metadata classes or something?
Basically I'd love for there to be a way for me to apply attributes to properties at runtime (i.e. inside the "Arrange" part of my test method), but I'm pretty sure that's impossible.
Edit
This is the reflection code I'm using to test attributes, since apparently how I'm reading them may make a difference:
bool skip = false, iip = false;
string lt = null;
SerializeAsOptions sa = SerializeAsOptions.Ids;
object[] attrs = prop.GetCustomAttributes(true);
foreach (object attr in attrs)
{
Type attrType = attr.GetType();
if (typeof(JsonIgnoreAttribute).IsAssignableFrom(attrType))
{
skip = true;
continue;
}
if (typeof(IncludeInPayload).IsAssignableFrom(attrType))
iip = ((IncludeInPayload)attr).Include;
if (typeof(SerializeAs).IsAssignableFrom(attrType))
sa = ((SerializeAs)attr).How;
if (typeof(LinkTemplate).IsAssignableFrom(attrType))
lt = ((LinkTemplate)attr).LinkTemplate;
}
if (skip) continue;
I'm adding another answer, because since you now provided some code, the old one is too broad. It's now (mostly) obvious that:
you control the attribute-reading code
you are reading the code via reflection (PropertyInfo.GetCustomAttributes)
So. Since you are using Reflection, TypeDescriptors will not help. You'd need to:
either read the attrs differently so TypeDescr can be used
dynamically generate assemblies at runtime to generate classes with properties on the fly during tests
It can be very interesting/entertaining, but it can also turn into nice amount of work. But, since you control both sides of the code, none of these two is actually needed.
First, let's trim the code to significant parts:
somemethod(PropertyInfo prop)
{
// ...
object[] attrs = prop.GetCustomAttributes(true); // read ATTRs from PROP
foreach (object attr in attrs) // scan the PROP's ATTRs
{
// check attr type, do something
}
// ...
}
The core of your problem is not:
adding/removing attributes during Arrange/Teardown part
but
forcing the loop over PROP's ATTRs to see attributes that your test specifies
Looking at the problem like this, the answer is almost obvious: your loop has to abstract from the "Read attributes" part.
object[] attributeReader(PropertyInfo prop)
{
return prop.GetCustomAttributes(true);
}
somemethod(PropertyInfo prop)
{
// ...
object[] attrs = attributeReader(prop); // read ATTRs from PROP
foreach (object attr in attrs) // scan the PROP's ATTRs
{
// check attr type, do something
}
// ...
}
Now, your processing code is independent of the way the attributes are read. Sure, in the example above that way is hardcoded. But it does not have to be. Depending on how you want/like to organize your tests, you can use many ways to replace the attributeReader method with other mechanisms.
For example, just add 'virtual' to the attributeReader and use inheritance to create a class that will enable AttributeFaking:
// original class:
virtual object[] attributeReader(PropertyInfo prop)
{
return prop.GetCustomAttributes(true);
}
// derived class:
object[] AttributesOverrides {get;set;}
override object[] attributeReader(PropertyInfo prop)
{
if(prop.Name = "ShoeSize") return AttributesOverrides; // return what I say!
return base.attributeReader(prop);
}
// your test setup
var t = ... // that DERIVED object
t.AttributesOverrides = new [] { ... } ; // attributes to use
For example, use delegates/lambdas, no inheritace
// note the attributeReader is now a field, not function
Func<PropertyInfo, object[]> attributeReader = defaultAttributeReader;
static object[] defaultAttributeReader(PropertyInfo prop)
{
return prop.GetCustomAttributes(true);
}
// and your test setup
var t = ... // that ORIGNAL object
t.attributeReader = customReaderForTheTest; // change the reader on the fly
// that's the reader-function to use in THIS TEST setup
static object[] customReaderForTheTest(PropertyInfo prop)
{
if(prop.Name = "ShoeSize") return null; // crash when I say so! muhaHAHAhaa!
return prop.GetCustomAttributes(true);
}
Both of those two examples end up with one class that is enables faking the attributes in some way, but that's not the only ways to do that. You can use IoC to inject the correct attributeReader. You can do that in any way you like - you just need to abstract from reading part and leave it 'open'.
It is not possible to really apply the attribute at runtime to an existing class, but there are at least two ways you could do something similar to it - it depends on how exactly are you reading those attributes later.
The options focus on the 'really' and 'existing class' part:
1) don't do that, just fake adding them
2) apply them on a class that does not exist yet! ;)
First option is a CustomTypeDescriptor. In its implementations, you will be able to dynamically answer to any queries about Attributes for some class that uses it (-> see virtual GetAttributes method).
This leads to first way:
Create AttributableTestObject that i.e. inherits from your ClassCompatibleWithThatAttribute etc
Create something like DynamicallyAttributedClass : CustomTypeProvider that exposes a static property similar to IEnumerable<Attribute>
override the GetAttributes and return whatever was provided by that static property
on your AttributableTestObject class set a TypeDecriptorProvider attribute pointing to provider (you've got to implement it, again) that returns DynamicallyAttributedClass
Now, using that static property you can change what the GetAttributes returns, and therefore you can dynamically change the setof attributes that are visible through typedescriptor.
And here's the catch: Not all engines/observers/readers/(..) actually care about TypeDescriptors. Some simply read the metadata right away from the Reflection. Reflection will not check the typedescriptors. It will simply return an information that the AttributableTestObject class has a TypeDecriptorProvider property. But whe nusing used the ComponentModel mechanisms, the custom list of attribues will be visible.
That reminds me that the reading mechanisms simply sit at TypeDescriptor class, see its methods. There's also AddAttribute, so maybe you can even get what you want without actually implementing the stuff I said above - Try using AddAttribute and then GetAttribute on your target Type and check the results. It may "just work". But again, it will not fool the reflection.
So, there's a second, "more hardcore" approach - dynamic classes. With System.Reflection.Emit you can dynamically generate an assembly that will contain whatever IL code you wish, and then load the assembly to the current runtime.
This gives you a unique option to simply generate a new fresh class(es) at runtime, with any contents and any attributes you like. You can use inheritance, so you can inherit from any ClassCompatibleWithThatAttributes. It's not that easy to do manually, but there are some libraries that make using the IL emitter easier.
Note that the generated types will be generated at runtime. This means that at compile-time you will not have them checked, you must generate them perfectly or face some really rarely seen Exceptions. Also, note that as the types are not known at compile-time, you cannot simply new the objects. You will have to create the objects basing on their freshly-generated Type through i.e. Activator.CreateInstance(Type).
Also, even though you can generate as much new classes as you want - if you overdo it, you probably will eventually hit some CLR limit, or at leat OutOfMemory, since the generated and loaded assemblies actually occupy space. You can overcome it with AppDomains - you can create some extra AppDomains and generate and load the assemblies inside them, and then, finally, you can unload that extra domain to release all memory and also unload any assemblies that were loaded there. But, I suppose you will not generate that much types to really need that. I'm writing about it just-in-case. Dont worry until you hit the OutOfMemory or similar.

AutoMapper IEnumerable mapping bug

I have a strange thing happening with automapper.
Do someone have a clue why this code is returning a value for the InstitutionsImplantations field :
var result1 = new List<DataModel.Implantations>();
foreach (var c in collection)
{
DataModel.Implantations i = Mapper.Map<DataModel.Implantations>(c);
result1.Add(i);
}
var item1 = result1.Where(x => x.Nom == "Valdor").FirstOrDefault();
Console.WriteLine(item1.InstitutionsImplantations);
While this one (on the same collection), return null for InstitutionsImplantations :
var result2 = Mapper.Map<IEnumerable<DataModel.Implantations>>(collection);
var item2 = result2.Where(x => x.Nom == "Valdor").FirstOrDefault();
Console.WriteLine(item2.InstitutionsImplantations);
Facts :
The mapping done by autommaper on the IEnumerable is correct for the +/- first 300 items in the list, then after, some item collection have a "badly" mapped InstitutionsImplantations property.
InstitutionsImplantations property is an object "proxy" from a EF result.
do you have an idea why this is happening ?
Tx you !
Found the problem, using the automapper source code to see what was going on behind the scenes.
When automapper is processing the IEnumerable collection, its using a caching mechanism to avoid to have to remap an already mapped object that was present in the collection.
You would say, its fair, no reason to have the same object mapped to a different result.
But in my scenario, I forget to add that I was also using an AfterMap delegate at the mapping declaration.
In this AfterMap I was doing this (To avoid circular references problem) :
mappedItem.InstitutionsImplantations.Institution.InstitutionsImplantations = null;
This problem of this is that, I though that it was only impacting the result of the mapping (AfterMap delegate), and nothing else, but I was wrong it is also impacting the "Cache" being put in place !
This is not was I wanted, because in this case it did also impact all following mapping computing in the collection, using "Null" for the following mapped InstitutionsImplantations object, instead of brand new mapping.
My first solution was clean because the caching mechanism did not work between 2 "different" mapping.
And I didn't find an easy way to disable this collection caching mechanism inside automapper !

AutoMapper - mapping properties from one EF4 entity to another in a loop without Before/AfterMap

It appears that AutoMapper's methods BeforeMap and AfterMap have a critical bug, which if one is attempting to iterate over a collection of the source object to populate a property of the destination object, those mapping methods execute more than once. See: Extra iterations in a foreach in an AutoMapper map
What I'm trying to do is a bit complicated, so please bear with me.
I have a EF4 many-to-many graph (Games-to-Platforms) I'm trying to build based on incoming form data. In order to build the graph, I take the raw integer ids that come from the form, and then grab the correct Platforms from my repository in order to add them to the Game's collection. You can see my attempt at doing this within BeforeMap in the link I provided above.
The problem is that I'm not sure how to proceed. I need to be able to grab a hold of the destination (Game) object in order to successfully Add the Platforms to the Game. Is something like this possible in ForMember? From what I've read, it doesn't look like a custom resolver would work for me, and I'm not sure how I'd implement a custom type converter given all the moving parts (two entities, repository).
Any ideas or suggestions?
I simply decided to make my own static mapper. Not an ideal, or even great solution, but it works. It can definitely be made more abstract, but I figure it's a band-aid until AutoMapper is fixed. My solution:
public static class GameMapper
{
public static Game Map(IGameRepository repo, AdminGameEditModel formData, Game newGame)
{
newGame.GameID = formData.GameID;
newGame.GameTitle = formData.GameTitle;
newGame.GenreID = formData.GenreID;
newGame.LastModified = DateTime.Now;
newGame.ReviewScore = (short)formData.ReviewScore;
newGame.ReviewText = formData.ReviewText;
newGame.Cons = String.Join("|", formData.Cons);
newGame.Pros = String.Join("|", formData.Pros);
newGame.Slug = formData.Slug;
if (newGame.Platforms != null && newGame.Platforms.Count > 0)
{
var oldPlats = newGame.Platforms.ToArray();
foreach (var oldPlat in oldPlats)
{
newGame.Platforms.Remove(oldPlat);
}
}
foreach (var platId in formData.PlatformIDs)
{
var plat = repo.GetPlatform(platId);
newGame.Platforms.Add(plat);
}
return newGame;
}
}
Unfortunately, I can't make the third parameter an out parameter due to my need to overwrite existing entity data during updating. Again, it's definitely not a pretty, or even good solution, but it does the job. I'm sure the OO gods will smite me at a later date.

Can I start with a string and instantiate an object of that string?

I am currently working with LINQ and C#.
I have a DropDownList of the tables in my LINQ to SQL model.
I want the user to be able to select a LINQ table name from the DropDown. In code I want to create an instance of that LINQ class and then run a Select or it or anything else I want.
How would I accomplish creating the object based on what object name in string the user chose? Am I thinking incorrectly from the start?
You want Type.GetType(string) and Activator.CreateInstance(Type).
Note that Type.GetType(string) will only look in the currently executing assembly and mscorlib unless you specify the full type name including assembly. In either case, you need to specify the type name including namespace.
Another alternative is to use Assembly.GetType(string) to get the type directly from the string before calling Activator.CreateInstance.
(There are actually lots of alternatives here. If none of these help you, please post more info and I'm sure we can work out a way to go.)
Since you tagged the post with ASP.NET, I am assuming that the list is on the client side. If that is the case, you should be very careful about trusting that data, and I would not recommend creating types directly from user input. You could use the data as input to a factory that could then return the proper instance (and handle any illegal input as you see fit).
Elaborating on Brian Rasmussen's warning: The types should be restricted and require conscious design. Preferable the "user-instantiable" types should be marked with a specific custom attribute that can be verified with reflection.
With LINQ-to-SQL, there are specific ways of doing this from the data-context; basically, db.GetTable. This returns an ITable, but it is a little tricky to work with an untyped ITable. You can enumerate it, at least...
To get the ITable, you normally need the Type, which you can get with (for example) Assembly.GetType:
using (var ctx = new MyDataContext()) {
string name = "Customer"; // type name
Type ctxType = ctx.GetType();
Type type = ctxType.Assembly.GetType(
ctxType.Namespace + "." + name);
ITable table = ctx.GetTable(type);
foreach(var row in table) {
Console.WriteLine(row); // works best if ToString overridden...
}
}
Of course, once you have the Type, you use use Activator to create new entity instances:
object newObj = Activator.CreateInstance(type);
// TODO: set properties (with reflection?)
table.InsertOnSubmit(newObj);
but if you want to use the property-name, that can work too:
using (var ctx = new MyDataContext()) {
string name = "Customers"; // property name
ITable table = (ITable) ctx.GetType()
.GetProperty(name).GetValue(ctx, null);
foreach (var row in table) {
Console.WriteLine(row); // works best if ToString overridden...
}
}
Running filters (Where) etc is tricky with untyped data, as building the Expression would be tortuous. I'd probably start switching to a typed model at that point...
To follow on Marc Gravell's answer.
Doing as he suggested, I noticed a Cast<TResult> extension method (defined in System.Linq).
Unfortunately you can't seem to be able to do use the type instance to cast:
Type dcType = dc.GetType();
Type type = dcType.Assembly.GetType(String.Format("{0}.{1}", dcType.Namespace, name));
var row = dc.GetTable(type).Cast<type>().SingleOrDefault(i => i.ID == 123);

Can attributes be added dynamically in C#?

Is it possible to add attributes at runtime or to change the value of an attribute at runtime?
This really depends on what exactly you're trying to accomplish.
The System.ComponentModel.TypeDescriptor stuff can be used to add attributes to types, properties and object instances, and it has the limitation that you have to use it to retrieve those properties as well. If you're writing the code that consumes those attributes, and you can live within those limitations, then I'd definitely suggest it.
As far as I know, the PropertyGrid control and the visual studio design surface are the only things in the BCL that consume the TypeDescriptor stuff. In fact, that's how they do about half the things they really need to do.
Attributes are static metadata. Assemblies, modules, types, members, parameters, and return values aren't first-class objects in C# (e.g., the System.Type class is merely a reflected representation of a type). You can get an instance of an attribute for a type and change the properties if they're writable but that won't affect the attribute as it is applied to the type.
You can't. One workaround might be to generate a derived class at runtime and adding the attribute, although this is probably bit of an overkill.
Well, just to be different, I found an article that references using Reflection.Emit to do so.
Here's the link: http://www.codeproject.com/KB/cs/dotnetattributes.aspx , you will also want to look into some of the comments at the bottom of the article, because possible approaches are discussed.
No, it's not.
Attributes are meta-data and stored in binary-form in the compiled assembly (that's also why you can only use simple types in them).
I don't believe so. Even if I'm wrong, the best you can hope for is adding them to an entire Type, never an instance of a Type.
If you need something to be able to added dynamically, c# attributes aren't the way. Look into storing the data in xml. I recently did a project that i started w/ attributes, but eventually moved to serialization w/ xml.
Why do you need to? Attributes give extra information for reflection, but if you externally know which properties you want you don't need them.
You could store meta data externally relatively easily in a database or resource file.
Like mentionned in a comment below by Deczaloth, I think that metadata is fixed at compile time. I achieve it by creating a dynamic object where I override GetType() or use GetCustomType() and writing my own type. Using this then you could...
I tried very hard with System.ComponentModel.TypeDescriptor without success. That does not means it can't work but I would like to see code for that.
In counter part, I wanted to change some Attribute values.
I did 2 functions which work fine for that purpose.
// ************************************************************************
public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName, string description)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, description);
}
}
}
// ************************************************************************
public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, isReadOnly);
}
}
}
When faced with this situation, yet another solution might be questioning you code design and search for a more object-oriented way. For me, struggling with unpleasant reflection work arounds is the last resort. And my first reaction to this situation would be re-designing the code. Think of the following code, which tries to solve the problem that you have to add an attribute to a third-party class you are using.
class Employee {} // This one is third-party.
And you have code like
var specialEmployee = new Employee();
// Here you need an employee with a special behaviour and want to add an attribute to the employee but you cannot.
The solution might be extracting a class inheriting from the Employee class and decorating it with your attribute:
[SpecialAttribute]
class SpecialEmployee : Employee
{
}
When you create an instance of this new class
var specialEmployee = new SpecialEmployee();
you can distinguish this specialEmployee object from other employee objects. If appropriate, you may want to make this SpecialEmployee a private nested class.

Categories