I'm sorry if this has been asked before, I tried many combinations of keywords to describe the issue but was unable to find anything on Google or SO.
The problem is simple: and I have a List of objects. I've marked this list with ObjectCollectionValidator so that objects get validated. Some of the objects in the list aren't, however, of type T, but of some derived type.
Those derived types have properties not present on their parents that need to be validated. They simply won't. I believe that VAB isn't checking inherited types when dealing with ObjectCollectionValidator, but that is a flaw in my opinion, so I'm hoping I'm wrong.
By the way, I'm using EntLib's 4.1 (and while I wanted, I cannot switch to EntLib 5.0).
What you're witnessing is a design quirk of VAB 4.1 that has been solved in VAB 5.0. In VAB 5.0, when you decorate a collection property with a ObjectCollectionValidatorAttribute, you can leave out the actual type and in that case, the validator will validate objects by their actual type.
If you can't switch to VAB 5.0, the only thing you can do is write your own object collection validator. This isn't really difficult. Just look at the source of of the ObjectCollectionValidatorAttribute and ObjectCollectionValidator of VAB 5.0.
Good luck.
Related
Preamble:
I'm working on implementing a system where a developer can specify on object of type T which has N number of properties.
What I'm trying to accomplish:
I'd like to be able to provide more concrete control over how these properties are set and retrieved. This is difficult because of the limitless number of configurations possible.
Solutions I'm pursuing:
Is it possible to set getters dynamically?
Either through attributes? Generate the methods after the fact during construction like :
foreach(var property in typeOf(T).GetProperties())
{
//dynamically generate getter method which returns this property.
}
Possibly wrap type T in a container object which has the type as one of its properties. Then set up some type of special getter for that.
Why I want to do this:
Currently all the types for T get converted based on Typecode. Allowing people using this library to easily parse in values from various sources (databases, text files, app configs, etc.) as properties of type T. The point being to deliver these properties as type safe values rather than magic strings.
This is the impetus for wanting to use reflection for this but I could see numerous other applications for this I would imagine.
I could just say "Hey make all of your types nullable." so that it would be easy to determine which properties have been set in type T. I'd like to abstract away even that though.
The other option for this would be "Make sure you understand that certain types have default values. Be certain you're ready to accept those values, or set default values of your own (including making it nullable and setting it to null if so desired). Essentially trusting this to the developer rather than abstracting it. <==== This is what I'm currently doing.
Being able to dynamically generate methods, especially getters and setters, dynamically via reflection or a combination of reflection and C# Actions would be incredibly valuable. Any insight or ideas would be greatly welcome. Either ways of accomplishing the solutions I'm pursuiing or another idea which achieves the same ends.
I don't believe you can set accessor methods on properties of static types. Another challenge that I think you will have to deal with will be your goal to provide type safety - you see, if your types are built in run-time, compile-time checks will not work, which means you'll have to rely on dynamic a lot - this is slow. But not all is lost. You have at least two options:
The quick and dirty way
You can generate proxy classes that would inherit from your concrete types. Theese will give you ability to intercept method calls to base members and do pretty much anything you please. See Castle DynamicProxy
The hard but proper way (actually first option is using this behind the scenes)
You're looking at IL Generator namespace. This is a step above linq expression trees in a sense that you can generate your own assembly and types, all programmatically. This however is incredibly complex and error prone. I'd suggest you try option one first and only generate your own IL if you absolutely must.
UPD I know you didn't want magic strings, an I guess this is a bit less conventional solution, but also check out CSharpCodeProvider of CodeDOM namespace
I find it a recurring inconvenience that a lot of simple types in the .Net framework are not marked as serializable. For example: System.Drawing.Point or Rectangle.
Both those structs only consist of primitive data and should be serializable in any format easily. However, because of the missing [System.Serializable] attribute, I can't use them with a BinaryFormatter.
Is there any reason for this, which I'm not seeing?
It is simply a question of efficiency. Tagging a field as serializable the compiler must map each field onto a table of aliases. If they were all marked as serializables every object injecting or inheriting them need to be mapped aswell onto the table of aliases to process its serialization when probably you will never use them and it has a cost of memory and processing and it is more unsafe. Test it with millions of elements and you will see.
Personally, I believe it has less to do with the need to pass the buck, and more to do with the fact of usefulness and actual use, coupled with the fact that the .NET Framework is simply that, a framework. It is designed to be a stepping stone which provides you the basics to complete tasks that would otherwise be daunting in other languages, rather than do everything for you.
There really isn't anything stopping you from creating your own serialization mechanisms and extensions which provide the functionality you're seeking, or relying on many of the other products out there which are FOSS or paid which achieve this for you OOB.
Granted, #Hans Passant's answer is I think very close to the truth, there's a lot of other facets to this which go beyond just simply "It's not my problem." You can take it whatever way you want, but the ultimate thing you need to get out of it is, "where can I go from here?"
After playing around with Asp.Net MVC for some time I have decided to actually use it in a project. One of the issues that came up is that the frontend site might have different validation rules for a given model than the admin panel.
I am aware of the MetadataType property but since you have more than one contexts this would not work for us out of the box.
In order to solve this I implemented a custom ModelMetadataProvider that redirects the default ModelMetdataProvider to a different type based on the request's execution context. This works pretty well for displaying the needed UI.
The part of this solution I do not like is that I ended up reading the stack from my custom model metadata provider to determine if the given call is for model binding. This is because when I did not do that I would correctly get "Object does not match target type" during the call to TryUpdateModel from the Controller since the model binder was trying to use properties from type A to set values to an instance of type B.
Is reading the call stack such a bad idea for production?
Is there a way to replicate the MetadataTypeAttribute behavior selectively without using attributes?
Thanks in advance,
John
This is one of those instances where you wish the ASP.NET MVC Team hadn't sealed a class - I'm sure they had their reasons. I was going to suggest simply creating your own attribute, derived from MetadataTypeAttribute.
One way to go about this is to take the source of the attribute and write your own:
http://dotnetinside.com/framework/v4.0.30319/framework/v4.0.30319/System.ComponentModel.DataAnnotations/MetadataTypeAttribute
Although, of course, this makes your code less maintainable.
I would assert that to the best of my knowledge, you are already making the right decision with a ModelMetadataProvider as your solution. I'm a little nervous for you regarding analysing the call stack though, change locations, move something to an area; you get my drift, i.e. it would be very easy to break the code with a build time decision that isn't found until runtime or beyond QA.
You haven't supplied how the context is roughly determined, but I would personally tackle that by adding a property to the class itself with an Enum (finite possibilities and design time breakage) with a list of possible contexts, then during spin up of the class, populate it, ready for execution of the Provider, which will pass through the correct metatdatatype based on the value of the Enum.
Many ways to skin this cat, but something that is going to break on build will serve you best, IMHO.
Unless you are using MVC 6 you may find ModelMetadata Fluent Configuration useful.
Some nice examples of how to use it can be found here and here.
What is really important is that it is just code which is completely under your control. Thus, once you have different contexts, you may decide to define different configurations, or you may play a bit harder and make (a set of) different registrations for different contexts.
What really helps is "decorating" (the term used on purpose!) properties of a base class, at least nothing seems to stooping you from doing it.
EDIT: Model Metadata shouldn't be confused with WCF RIA Services Contrib.
I was wondering, why on some occasions i see a class representing some type's collection.
For example:
In Microsoft XNA Framework: TextureCollection, TouchCollection, etc.
Also other classes in the .NET framework itself, ending with Collection.
Why is it designed this way? what are the benefits for doing it this way and not as a generic type collection, like was introduced in C# 2.0 ?
Thanks
The examples you gave are good ones. TextureCollection is sealed and has no public constructor, only an internal one. TouchCollection implements IList<TouchLocation>, similar to the way List<T> implements IList<T>. Generics at work here btw, the upvoted answer isn't correct.
TextureCollection is intentionally crippled, it makes sure that you can never create an instance of it. Only secret knowledge about textures can fill this collection, a List<> wouldn't suffice since it cannot be initialized with that secret knowledge that makes the indexer work. Nor does the class need to be generic, it only knows about Texture class instances.
The TouchCollection is similarly specialized. The Add() method throws a NotSupportedException. This cannot be done with a regular List<> class, its Add() method isn't virtual so cannot be overridden to throw the exception.
This is not unusual.
In the .NET framework itself, many type-safe collections predate 2.0 Generics, and are kept for compatibility.
For several XAML-related contexts, there's either no syntax to specify a generic class, or the syntax is cumbersome. Therefore, when List<T> wiould be used, there's a specific TList written for each need.
It allows you to define your own semantics on the collection (you may not want to have an Add or AddRange method etc...).
Additionally, readability is increased by not having your code littered with List<Touch> and List<Texture> everywhere.
There is also quite a lot of .NET 1.0/1.1 code that still needs to work, so the older collections that predate generics still need to exist.
It's not that easy to use generic classes in XAML for example.
Following on from Oded's answer, your own class type allows for much easier change down the track when you decide you want a stack / queue etc instead of that List. There can be lots of reasons for this, including performance, memory use etc.
In fact, it's usually a good idea to hide that type of implementation detail - users of your class just want to know that it stores Textures, not how.
I have a WCF service that uses generics in its data contract, for example (simplified):
public GetDetails(StatusField<string> status);
Now WCF supports generics by creating a non-generic equivalent type for every possible value of T in the generic. So, for the above example, the client consuming the WCF service will see the following signature for the above function:
public GetDetails(stringStatusField status);
//...
Now the client has a copy of the generic version of the StatusField class. We want to use AutoMapper in the client, to map between this generic StatusField and the types generated above by WCF (such as stringStatusField) so we can call the service. We could do this by manually creating the maps at client startup, like so:
Mapper.CreateMap<StatusField<string>, stringStatusField>();
However this is laborious as there are 50+ possible values of that WCF has converted. Extending this idea, we could use reflection to automatically create maps for all the types and this is the solution we are currently using.
Ideally what i would like to see is a solution that ties into the architecture of AutoMapper to avoid having to do the reflection manually. conceptually, this would require some way of defining a convention that AutoMapper would use to allow it to tie the two types together, similar to how it allows custom conventions to be specified when matching properties. As yet, i have not seen a way to do this and this is the question i would like answered here, if anyone knows how this can be done, specifically in relation to the above scenario.
BTW i am aware that some may be thinking of Mapper.DynamicMap() as a solution to this problem. Firstly, we dont want to use this as it means debugging could potentially be harder (as indicated by some in other posts similar to this) and also if the StatusField is deeply nested in an object graph being passed to the WCF method, im not sure this solution would work and could potentially lead to a type being incorrectly mapped and other such issues. I would really like to concretely define the allowable mappings if possible.
Unsure if AutoMapper provides the support you are after, but if it did it would be using reflection as you propose.
If you are opposed to the reflection solution due to performance concerns (which should be a one-time startup cost), then maybe a T4 template-based code generation solution might be worth considering?