Exception when querying with an explicit Interface using MongoDB C# driver - c#

I need to construct a query using as a FilterDefinition an explicit Interface but it throws an exception saying :
System.InvalidOperationException
Message={document}.Pointer is not supported.
Source=MongoDB.Driver
I have tried this with normal Interface implementation and it works as expected.
But I need to implement an Interface explicitly as I'm having 2 interfaces with the same property names as shown in the code below:
public class Offer : OfferBase, IPointerTo<ServiceCategory>,
IPointerTo<Company>
{
[BsonElement("_p_ServiceCategoryObj")]
[JsonProperty("serviceCategoryObj")]
string IPointerTo<ServiceCategory>.Pointer { get; set; }
[BsonElement("_p_companyObj")]
[JsonProperty("companyObj")]
string IPointerTo<Company>.Pointer { get; set; }
}
So, I create a FilterDefinition that I will use in a Find.
As I mentioned before, this works fine if it were not an explicit interface implementation. For instance: if just use one of them normally implemented and the other explicitly it will work when querying for the normal one. But having the above code constraints and creating the filter like this:
FilterDefinition<Offer> innnerFilter = MongoQueryBuilder.AddFilter<Offer>
(offer =>string.IsNullOrEmpty((offer as
IPointerTo<ServiceCategory>).Pointer));
So when the Find with that filter is being executed the exception stated above is being thrown.
Note: MongoQueryBuilder.AddFilter is just a wrapper that I did to make it easier but that it's not the issue as all the other queries work fine using that.
I would expect to get the results as I get them when just having one of the interfaces implemented normally and querying with that Interface member but in my current scenario I need to have them both implemented and thus they must be implemented explicitly.
I may not be doing something properly or using it as I should but I haven't been to find any solution to this.
Edit: (thanks to #Lakerfield answer)
I was not able to find Pointer as I was asking for Offer and as Pointer it's an explicit interface it was not being able to publicly find it.
So, I was able to solve it like this:
public class Offer : OfferBase, IPointerTo<ServiceCategory>, IPointerTo<Company>
{
[BsonIgnoreIfNull]
[BsonIgnoreIfDefault]
[BsonElement("_p_ServiceCategoryObj")]
[JsonProperty("serviceCategoryObj")]
public string ServiceCategoryPointer
{
get => (this as IPointerTo<ServiceCategory>).Pointer;
set => (this as IPointerTo<ServiceCategory>).Pointer = value;
}
[BsonIgnore]
string IPointerTo<ServiceCategory>.Pointer { get; set; }
[BsonIgnoreIfNull]
[BsonIgnoreIfDefault]
[BsonElement("_p_companyObj")]
[JsonProperty("companyObj")]
public string CompanyPointer
{
get => (this as IPointerTo<Company>).Pointer;
set => (this as IPointerTo<Company>).Pointer = value;
}
[BsonIgnore]
string IPointerTo<Company>.Pointer { get; set; }
And then doing the query like this: (Now I'm use Linq instead of FilterDefinition but that is not relevant for the sake of this solution)
private static Expression<Func<Offer, bool>> InnerQueryServiceCategory(string serviceCategoryId)
{
return offer => (offer.IsDeleted == false || !offer.IsDeleted.HasValue) && offer.ServiceCategoryPointer == PointedCollections.ServiceCategoryCollection.GetDescription() + serviceCategoryId;
}
offer.ServiceCategoryPointer is publicly available and it's a member of Offer.

The problem is the duplicate Pointer property name. In MongoDB a object must have unique propertynames.
Workaround just use two seperate properties with different names, forward your explicit interfaces to those, and use the new properties in your query.
public class Offer : OfferBase, IPointerTo<ServiceCategory>, IPointerTo<Company>
{
public string ServiceCategoryPointer { get; set; }
public string CompanyPointer { get; set; }
string IPointerTo<ServiceCategory>.Pointer
{
get => ServiceCategoryPointer;
set => ServiceCategoryPointer = value;
}
string IPointerTo<Company>.Pointer
{
get => CompanyPointer;
set => CompanyPointer = value;
}
}

Related

Comparison of unspecified generic properties

Consider the following code:
public interface IIdentifiable<T>
{
T Id { get; set; }
}
public interface IViewModel
{
}
public class MyViewModel1 : IViewModel, IIdentifiable<int>
{
public string MyProperty { get; set; }
public int Id { get; set; }
}
public class MyViewModel2 : IViewModel, IIdentifiable<string>
{
public string MyProperty { get; set; }
public string Id { get; set; }
}
I also have class that operates with ViewModels:
public class Loader<T> where T: IViewModel
{
public void LoadData()
{
/*some important stuff here*/
if (typeof(IIdentifiable<??>).IsAssignableFrom(typeof(T)))
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<??>) ds).Id != ((IIdentifiable<??>) d).Id)).ToList();
} // ^---- and there the second ----^
/*some important stuff here too*/
}
}
Now, as you can see, viewmodels that I have might implement the IIdentifiable<> interface. I want to check that, and if it's true,
I want to make sure my data list does not contains any entry that are already present in my _dataSourse list.
So I have 2 questions:
I don't know what IIdentifiable<> has in its generic parentheses, it might be int, string or even GUID.
I tried typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) which is the correct syntax, yet it always returns false.
Is there a way to check whether T is IIdentifiable<> without knowing the exact generic type?
If there is an answer for the first question, I would also like to know how can I compare the Id fields without knowing their type.
I found this answer quite useful, yet it doesn't cover my
specific case.
I know that I probably can solve that problem if I make my Loader<T> class a generic for two types Loader<T,K>, where K would be the
type in IIdentifiable<>, yet I would like to know if there are other solutions.
P.S. In addition to my first question: I'm also curious why one can write something like this typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) if it returns false when the generic type of IIdentifiable<> is not specified?
Edit: I guess, in hindsight, I understand why I can't write the code this bluntly - because there's might be the collection ICollection<IViewModel> where the entries implement different types of IIdentifiable<> (or don't implement it at all), and the check like that would fail awkwardly. Yet maybe there is a way to do something like that with some restrictions, but without creating second generic parameter to my Loader?
Try add two methods to your Loader<T>:
public bool CanCast<TId>()
{
var identifiableT = typeof(IIdentifiable<>).MakeGenericType(typeof(TId));
return identifiableT.IsAssignableFrom(typeof(T));
}
public IEnumerable<IIdentifiable<TId>> Filter<TId>(IEnumerable<T> data)
{
return data.Where(d => _dataSource.All(
ds => !((IIdentifiable<TId>) ds).Id.Equals(((IIdentifiable<TId>) d).Id)));
}
Then in LoadData
if (CanCast<int>())
data = Filter<int>(data);
else if (CanCast<Guid>())
data = Filter<Guid>(data);
// and so om
Well, I would suggest you to always use a string for identification. You can convert int and guid to a string. And if you want to ensure proper type is used then you can prefix the string with type information.
However, I do think that the performance of you algorithm would be very poor as you wouls essentially loop 2 containers so it would be O(n * m).
Thus it would be best to either do appropriate SQL query if both sources are from the database or use a dictionary if you do it in code. Alternatively if data is properly sorted, you could find duplicates more efficiently.
By the way generics are quite limited in C#. Sometime using ˋFunc<>ˋ could help but even then you have to provide extra information to the algorithm.
We should address your question in two steps (because there really are two problems to solve here).
First, make following change to your interface IIdentifiable<T>
public interface IIdentifiable<T>
where T : IEquatable<T>
{
T Id { get; set; }
}
This will ensure that you can compare Id properties correctly.
Secondly, in your LoadData() method, change the if statement to
if (T is IIdentifiable<T>)
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<T) ds).Id != ((IIdentifiable<T) d).Id)).ToList();
}

How to let an Attribute in property 'A' know the existence of property 'B'?

How to let an Attribute in one property know the existence of another property?
Lets say i have this class, and like this, many others:
public class MyClass
{
[CheckDirty] //a custom attribute (that it is empty for now)
public int A { get; set; }
public int B { get; set; }
public string Description { get; set; }
public string Info { get; set; }
}
Somewhere in our program, if we want to see if an object changed values on any CheckDirty property, for example lets say it is diferent from DB, MyPropertyUtils.GetPropertiesIfDirty() does this, giving us an array of changed propertys, on any property with that attribute:
PropertyInfo[] MyPropertyUtils.GetPropertiesIfDirty(SomeBaseObject ObjectFromDB, SomeBaseObject NewValues);
Perfect.
So, lets say A changed and in this case Info holds some information we need(in another class might be any other property). If we want 'A' we just do property.GetValue(NewValues, null);
But we dont want 'A's value, we want 'A' or CheckDirty to tell us where to read some data we want. How can i tell my attribute CheckDirty where to get the values from?
I was thinking in giving an expression to CheckDirty but an Attribute's argument "must be a constant expression, typeof expression or array creation expression of an attribute parameter type"(thats what VS says).
So I decided, "ok, lets give it a string with the property's name", and so my try failed:
(this is all the code we need to work on, the rest was just to give some kind of context example)
public class CheckDirty : Attribute
{
public String targetPropertyName;
public CheckDirty(String targetPropertyName)
{
this.targetPropertyName = targetPropertyName;
}
}
public class MyClass
{
//Code fails on this line
[CheckDirty(BoundPropertyNames.Info)]
public int Id { get; set; }
public string Info { get; set; }
public static class BoundPropertyNames
{
public static readonly string Info = ((MemberExpression)
((Expression<Func<MyClass, string>>)
(m => m.Info)
).Body
).Member.Name;
}
}
This is the error i get:
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
We do NOT want to pass the name of the proprety as a String saing [CheckDirty("Info")] because that way if anyone in the future changes the class, and in concrete the property's name, no error would get thrown in compile time by it, only occuring the error in run time, when an "edit" to that field would occur. Or maybe it would just not do anything because it could not find the property.
Any idea how to not use the strongly typed string as a property name?
You may use something like this, first declare an interface that will be implemented by every class that need dirty checking:
interface IDirtyCheckPropertiesProvider {
string GetPropertyName(string dirtyProperty);
}
then implement it like that
class DataEntity : IDirtyCheckPropertiesProvider {
[CheckDirty]
public int Id { get; set; }
public string Info { get; set; }
string GetPropertyName(string dirtyProperty) {
if (GetPropertyNameFromExpression(x => Id) == dirtyProperty)
return GetPropertyNameFromExpression(x => Info);
return null;
}
}
In class that will be responsible for handling dirty checks you must use this interface to get target property names.
There is a bit too much boilerplate that may be removed further by using Reflection API.
On the other hand using string for property names looks like more simple solution. If you use tool like Resharper - using string is a viable option - Resharper will automatically refactor string when you change property name.
Also for a long time string'ed property names were used in implementation of WPF INotifyPropertyChanged.
As comments suggested nameof is the best option in VS2015.

C#, How to simply change order of class members

Hi I Have a class derived from another class . Like this :
public class Customer
{
public string Date{ get; set; }
public string InstallationNo{ get; set; }
public string SerialNo { get; set; }
}
Then I have created a class named Customer_U which derived from Customer
public class Customer_U:Customer
{
public string Bill{ get; set; }
}
I have simple question. I have google many time but no answer. I have list filled with data like:
List<Customer_U> customer= new List<Customer_U>() I create a excel using this list. In excel colum order is like this :
Bill --- Date --- InstalltionNo --- SerialNo.
Idont want this order. I want "Bill" member to be last columns . How to set order of member when createin a class derived from another class
There is no defined order in a CLR class; it is up to the implementation that is inspecting the metadata of the class to determine how a class is interpreted.
For example, your Excel library is probably using reflection to inspect the class you pass it and reflection makes no guarantees as to the order in which things are processed.
Other implementations such as the WCF DataContractSerializer or ProtoBuf.NET handle order through the use of DataMember.
That said, if your library can handle dynamic or anonymous types then you can use the approach detailed in the other answers. .NET seems to consistently reflect these types in the same order that they were created.
var x = new { Z = "", Y = 1, X = true };
Console.WriteLine(x.GetType().GetProperties().Select(y => y.Name));
However it should be noted that this is an implementation detail and should not be relied upon. I'd see if you library allows you to specify the mapping between properties in your class and columns in your spreadsheet otherwise you might run into weird bugs in the future!
There is no ordering of class members in .NET. Whenever someone iterates over members in a class, they are imposing some order themselves.
The default seems to be shallow-first. So in your case, first all of Customer_U members are enumerated, and then Customer's.
If you do the enumeration yourself, there's nothing easier than simply using your own enumeration method:
class A
{
public string Date { get; set; }
public string SerialNo { get; set; }
}
class B : A
{
public string Bill { get; set; }
public string InstallationNo { get; set; }
}
public static IEnumerable<PropertyInfo> GetProperties(Type type)
{
if (type.BaseType == typeof(object)) return type.GetProperties().OrderBy(i => i.Name);
return GetProperties(type.BaseType)
.Concat
(
type
.GetProperties
(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
.OrderBy(i => i.Name)
);
}
This simple recursive method will output
Date
SerialNo
Bill
InstallationNo
Deep-first, alphabetical. If you don't want the alphabetical sort, you can omit the OrderBys, but note that then the order is simply unspecified, not necessarily the order you used in your class.
You can use this when building your Excel, for example - if there's a way to impose an order in the output data. If there's no way to impose your own order in whatever you're using to output your data, you could do a mapping to a new object based on this data, and hope that it turns out well - however, doing this dynamically is actually quite a bit of work.
As the other answers have pointed out, there is no such thing as a defined order for class properties in .NET.
However, it seems that what you are looking for is not an ordering of the properties themselves, but in fact a way to sort the properties when serializing the objects, e.g. to Excel.
This IS easily implemented using classes from the System.Runtime.Serialization namespace. There are various classes there that could help you control the serialization process, and allow you to be as specific as you want.
The simplest solution would likely be simply applying the DataMember attribute:
[DataContract]
public class Customer
{
[DataMember(Order = 1)]
public string Date{ get; set; }
[DataMember(Order = 2)]
public string InstallationNo{ get; set; }
[DataMember(Order = 3)]
public string SerialNo { get; set; }
}
You can create a new anonymous class using linq:
var x = from costumerItem in YourList
select new { Date = costumerItem.Date, ...and so on };
Afterwards, move this class to the excel.
Create a wrapper list like
var reOrderedCustomer = Customer.select(a => new { a.Date, a.InstallationNo ,
a.SerialNo, a.Bill }).ToList()
Or do this in your first select method which fills Customer list (If you want to avoid anonymous type)

Entity Framework: read only property vs parameter-less method

Consider following class
public class AccountGroup : Entity<int>
{
public AccountGroup()
{
Accounts = new HashSet<Account>();
Groups = new HashSet<AccountGroup>();
}
// option 1 - read only properties
public bool IsRoot { get { return Parent == null; } }
public bool IsLeaf { get { return !Groups.Any(); } }
public Account MainAccount { get { return Accounts.FirstOrDefault(a=>a.Type == AccountType.MainAccount); } }
// option 2 - parameter-less methods
//public bool IsRoot() { return Parent == null; }
//public bool IsLeaf() { return !Groups.Any(); }
//public Account GetMainAccount() { return Accounts.FirstOrDefault(a => a.Type == AccountType.MainAccount); }
public string Name { get; set; }
public string Description { get; set; }
public virtual ISet<Account> Accounts { get; private set; }
public virtual ISet<AccountGroup> Groups { get; private set; }
public virtual AccountGroup Parent { get; set; }
}
If I want to "enrich" the class above, which option approach should I use.
Option 1
Should I use read only parameters knowing that EF does not like them (trying to use IsRoot in Where clause throws ex, with The specified type member 'IsRoot' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
Option 2
Or should I go with parameter-less methods (not sure what would be disadvantages)
In general (not considering EF), which approach is preferred considering above when functionality is equivalent (i.e. I get the same functionality if I invoke .IsRoot or .IsRoot())
IsRoot feels more like a property to me. It represents current state of the object, doesn't actually do anything when invoked other than report that state, and generally getters/setters in .NET are properties.
There are other things to consider, a JSON/XML serializer will not serialize IsRoot() but will for IsRoot as a property. Generally speaking a lot of things in .NET hinge off of properties, so often they are the better choice.
EF wouldn't like IsRoot() either, it just doesn't know how to translate IsRoot into SQL, whether it's a property or method.
In general (as you say, not taking limitations of EF into account), the approach for domain models in this particular context would probably be a read-only property.
Consider that the property is simply checking state, not modifying it in any way. A read-only property conveys, outside of the object, that it's just returning a piece of information. On the other hand, a method could be potentially destructive in that it might modify information.
This would be particularly true if the method returned void of course, which isn't the case here, so this could be considered a borderline issue (and not even a question in languages which don't have "properties" but just use accessor methods, which under the hood is what a "property" does).
My vote is for a property when checking state and a method when commanding the object to modify state.
Have you already tried decorating IsRoot with [NotMapped]? The NotMapped attribute should prevent Entity Framework from complaining about properties that it's unable to persist and allow you to express that as a property.

`Type.GetProperties` property order

Short Version
The MSDN documentation for Type.GetProperties states that the collection it returns is not guaranteed to be in alphabetical or declaration order, though running a simple test shows that in general it is returned in declaration order. Are there specific scenarios that you know of where this is not the case? Beyond that, what is the suggested alternative?
Detailed Version
I realize the MSDN documentation for Type.GetProperties states:
The GetProperties method does not return properties in a particular
order, such as alphabetical or declaration order. Your code must not
depend on the order in which properties are returned, because that
order varies.
so there is no guarantee that the collection returned by the method will be ordered any specific way. Based on some tests, I've found to the contrary that the properties returned appear in the order they're defined in the type.
Example:
class Simple
{
public int FieldB { get; set; }
public string FieldA { get; set; }
public byte FieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Simple Properties:");
foreach (var propInfo in typeof(Simple).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
Output:
Simple Properties:
FieldB
FieldA
FieldC
One such case that this differs only slightly is when the type in question has a parent who also has properties:
class Parent
{
public int ParentFieldB { get; set; }
public string ParentFieldA { get; set; }
public byte ParentFieldC { get; set; }
}
class Child : Parent
{
public int ChildFieldB { get; set; }
public string ChildFieldA { get; set; }
public byte ChildFieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Parent Properties:");
foreach (var propInfo in typeof(Parent).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
Console.WriteLine("Child Properties:");
foreach (var propInfo in typeof(Child).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
Output:
Parent Properties:
ParentFieldB
ParentFieldA
ParentFieldC
Child Properties:
ChildFieldB
ChildFieldA
ChildFieldC
ParentFieldB
ParentFieldA
ParentFieldC
Which means the GetProperties method walks up the inheritance chain from bottom up when discovering the properties. That's fine and can be handled as such.
Questions:
Are there specific situations where the described behavior would differ that I've missed?
If depending on the order is not recommended then what is the recommended approach?
One seemingly obvious solution would be to define a custom attribute which indicates the order in which the properties should appear (Similar to the Order property on the DataMember attribute). Something like:
public class PropOrderAttribute : Attribute
{
public int SeqNbr { get; set; }
}
And then implement such as:
class Simple
{
[PropOrder(SeqNbr = 0)]
public int FieldB { get; set; }
[PropOrder(SeqNbr = 1)]
public string FieldA { get; set; }
[PropOrder(SeqNbr = 2)]
public byte FieldC { get; set; }
}
But as many have found, this becomes a serious maintenance problem if your type has 100 properties and you need to add one between the first 2.
UPDATE
The examples shown here are simply for demonstrative purposes. In my specific scenario, I define a message format using a class, then iterate through the properties of the class and grab their attributes to see how a specific field in the message should be demarshaled. The order of the fields in the message is significant so the order of the properties in my class needs to be significant.
It works currently by just iterating over the return collection from GetProperties, but since the documentation states it is not recommended I was looking to understand why and what other option do I have?
The order simply isn't guaranteed; whatever happens.... Happens.
Obvious cases where it could change:
anything that implements ICustomTypeDescriptor
anything with a TypeDescriptionProvider
But a more subtle case: partial classes. If a class is split over multiple files, the order of their usage is not defined at all. See Is the "textual order" across partial classes formally defined?
Of course, it isn't defined even for a single (non-partial) definition ;p
But imagine
File 1
partial class Foo {
public int A {get;set;}
}
File 2
partial class Foo {
public int B {get;set:}
}
There is no formal declaration order here between A and B. See the linked post to see how it tends to happen, though.
Re your edit; the best approach there is to specify the marshal info separately; a common approach would be to use a custom attribute that takes a numeric order, and decorate the members with that. You can then order based on this number. protobuf-net does something very similar, and frankly I'd suggest using an existing serialization library here:
[ProtoMember(n)]
public int Foo {get;set;}
Where "n" is an integer. In the case of protobuf-net specifically, there is also an API to specify these numbers separately, which is useful when the type is not under your direct control.
For what it's worth, sorting by MetadataToken seemed to work for me.
GetType().GetProperties().OrderBy(x => x.MetadataToken)
Original Article (broken link, just listed here for attribution):
http://www.sebastienmahe.com/v3/seb.blog/2010/03/08/c-reflection-getproperties-kept-in-declaration-order/
I use custom attributes to add the necessary metadata myself (it's used with a REST like service which consumes and returns CRLF delimited Key=Value pairs.
First, a custom attribute:
class ParameterOrderAttribute : Attribute
{
public int Order { get; private set; }
public ParameterOrderAttribute(int order)
{
Order = order;
}
}
Then, decorate your classes:
class Response : Message
{
[ParameterOrder(0)]
public int Code { get; set; }
}
class RegionsResponse : Response
{
[ParameterOrder(1)]
public string Regions { get; set; }
}
class HousesResponse : Response
{
public string Houses { get; set; }
}
A handy method for converting a PropertyInfo into a sortable int:
private int PropertyOrder(PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}
Even better, write is as an extension:
static class PropertyInfoExtensions
{
private static int PropertyOrder(this PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}
}
Finally you can now query your Type object with:
var props = from p in type.GetProperties()
where p.CanWrite
orderby p.PropertyOrder() ascending
select p;
Relying on an implementation detail that is explicitly documented as being not guaranteed is a recipe for disaster.
The 'recommended approach' would vary depending on what you want to do with these properties once you have them. Just displaying them on the screen? MSDN docs group by member type (property, field, function) and then alphabetize within the groups.
If your message format relies on the order of the fields, then you'd need to either:
Specify the expected order in some sort of message definition. Google protocol buffers works this way if I recall- the message definition is compiled in that case from a .proto file into a code file for use in whatever language you happen to be working with.
Rely on an order that can be independently generated, e.g. alphabetical order.
1:
I've spent the last day troubleshooting a problem in an MVC 3 project, and it all came down to this particular problem. It basically relied on the property order being the same throughout the session, but on some occations a few of the properties switched places, messing up the site.
First the code called Type.GetProperties() to define column names in a dynamic jqGrid table, something that in this case occurs once per page_load. Subsequent times the Type.GetProperties() method was called was to populate the actual data for the table, and in some rare instances the properties switched places and messed up the presentation completely. In some instances other properties that the site relied upon for a hierarchical subgrid got switched, i.e. you could no longer see the sub data because the ID column contained erroneous data. In other words: yes, this can definitely happen. Beware.
2:
If you need consistent order throughout the system session but not nessecarily exactly the same order for all sessions the workaround is dead simple: store the PropertyInfo[] array you get from Type.GetProperties() as a value in the webcache or in a dictionary with the type (or typename) as the cache/dictionary key. Subsequently, whenever you're about to do a Type.GetProperties(), instead substitute it for HttpRuntime.Cache.Get(Type/Typename) or Dictionary.TryGetValue(Type/Typename, out PropertyInfo[]). In this way you'll be guaranteed to always get the order you encountered the first time.
If you always need the same order (i.e. for all system sessions) I suggest you combine the above approach with some type of configuration mechanism, i.e. specify the order in the web.config/app.config, sort the PropertyInfo[] array you get from Type.GetProperties() according to the specified order, and then store it in cache/static dictionary.

Categories

Resources