To give an idea of my requirement, consider these classes -
class A { }
class B {
String m_sName;
public String Name {
get { return m_sName; }
set { m_sName = value; }
}
int m_iVal;
public int Val {
get { return m_iVal; }
set { m_iVal = value; }
}
A m_objA;
public A AObject {
get { return m_objA; }
set { m_objA = value; }
}
}
Now, I need to identify the classes of the objects passed to a function
void MyFunc(object obj) {
Type type = obj.GetType();
foreach (PropertyInfo pi in type.GetProperties()) {
if (pi.PropertyType.IsClass) { //I need objects only
if (!type.IsGenericType && type.FullName.ToLower() == "system.string") {
object _obj = pi.GetValue(obj, null);
//do something
}
}
}
}
I don't like this piece of code -
if (!type.IsGenericType && type.FullName.ToLower() == "system.string") {
because then i have to filter out classes like, System.Int16, System.Int32, System.Boolean and so on.
Is there an elegant way through which I can find out if the object is of a class defined by me and not of system provided basic classes?
One possible approach would be to use the Type.Assembly property and filter out anything that is not declared in one of your assemblies. The drawback of this approach is that you need to know all your assemblies at execution time, which might be hard in certain (not as common) scenarios.
There isn't really a reliable way. One thing that comes to mind is to look at the assembly the given type is defined: type.Assembly and compare this against a list of known assemblies.
As far as I Know there is no way to know if a class is from the BCL or is a user defined class but maybe you could just cache some assembly information from some well known framework dll.
You could cycle through all the classes in mscorlib.dll and put them into a List and then checking your class names against that list.
You could have a look at the PublicKeyToken attribute of the AssemblyQualifiedName on the type's Assembly property. But you would have to gather up the different tokens used by the framework for different versions of the runtime and compare to those.
The easiest way, if you have the possibility, is to mark your own classes with an attribute that you can check for (instead of checking for generics and the name of the type).
I've got a cheap and quick solution that might work:
if( type.IsClass && ! type.IsSealed )
The System.String object is a class but it is also sealed against inheritance. This works as long as you aren't using sealed classes in your code.
Related
I'm working with a client's API that has multiple different 'services' (around 10 so far), each one imports as its own namespace. Part of their standard API call pattern involves returning an array of error messages:
public class Error {
public String ErrorMessage {get;set}
public int errorNumber {get;set}
..etc
}
I've been trying to clean up and unify our handling of those messages. I tried to make a single function to handle them, eg:
void CheckErrors(List<Error> errors) {
if(errors != null && errors.Count() > 0)
throw new Exception(errors.First().ErrorMessage);
}
(the actual function is more complex but that gives the general idea)
However, it turns out that every one of their services has its own (identical) definition of this Error class. In C++ I could just template this function and it would work fine, or in a dynamic language it'd just work, but in C# I haven't been able to find a way to do this without making 10+ copies of the same function, each with a different namespace on the Error type.
In my own code I could just add an interface to these classes, but since it's not my code I don't think you can do that in C#? I could make a wrapper class that inherits from each of these and implements the interface, but I'm still stuck with duplicate code for every namespace/service.
Is there any cleaner way to handle this?
You could consider using a late binding solution either using reflection or dynamic. Both have the same drawback: you loose compile time type safety but if its a very isolated and contained piece of code it should be tolerable:
Reflection
void CheckErrors(List<object> errors) {
if(errors != null && errors.Count() > 0)
{
var firstError = errors.First();
throw new Exception(
firstError.GetType()
.GetProperty("ErrorMessage")
.GetValue(firstError)
.ToString()); }
Dynamic
void CheckErrors(List<dynamic> errors) {
if(errors != null && errors.Count() > 0)
throw new Exception(errors.First().ErrorMessage); }
Bear with me... you may need yet another Error class that is identical in properties to their Error class, but that you define in your namespace.
Your method CheckErrors uses your definition of Error.
Finally, you can use AutoMapper to map between their Error types and yours. This is pretty much exactly what AutoMapper is designed for. Since all your contracts are identical, the AutoMapper configuration should be trivial. Of course, you incur some runtime expense of mapping, but I think this would lead to the cleanest statically typed solution given that you can't change their interfaces.
The AutoMapper config + usage will look something like this:
//See AutoMapper docs for where to put config, it shouldn't happen on every call
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<TheirApi.Error, MyNamespace.MyErrorDefinition>();
}
var mapper = config.CreateMapper();
MyErrorDefinition myErrors = mapper.Map<List<MyErrorDefinition>>(listOfTheirErrorObjects);
CheckErrors(myErrors);
Another way is to use lambdas:
void CheckErrors<T>(IEnumerable<T> errors, Func<T,string> getMessage)
{
if (errors?.Count() > 0) throw new Exception(getMessage(errors.First()));
}
Then call it like this:
CheckErrors(errors, (e) => e.ErrorMessage);
I would define my own Error class that has a constructor that accepts any error object from your vendor and converts it. For example:
public class Error
{
public string Message { get; private set; }
public int ErrorNumber { get; private set; }
public Error(object vendorError)
{
var t = vendorError.GetType();
foreach (var source in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
foreach (var dest in typeof(Error).GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (dest.Name != source.Name) continue;
if (dest.PropertyType != source.PropertyType) continue;
dest.SetValue(this, source.GetValue(vendorError, null));
}
}
}
}
Then when you have an error list from your third party library, you can convert it using LINQ:
var myErrorList = vendorErrorList.Select( e => new Error(e) );
And now you can access the properties per normal.
See my example on DotNetFiddle
Is it possible when looking at a class' properties to detect if any of them is a reference type.
Take below as an example:
public class Client
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ProgrammeClient
{
public int Id { get; set; }
public bool IsActive { get; set; }
public IClient Client { get; set; }
}
ProgrammeClient: -
Id and IsActive are properties but Client is a reference type. Is there a way of detecting this?
Many thanks,
Kohan.
Addendum
The reason i ask is: I am using a mapper that checks types are the same before matching property names and copying the values. My hope is to detect classes and override the type matching and simply copy the classes properties if the THEY type match.
Well, it sounds like you may be trying to detect the difference between a value type and a reference type. You can find that out using Type.IsValueType... but be aware that value types can easily have properties too. (Think about DateTime for example.) Also, some types which you may want to regard as "not objects" are reference types - string being a prime example.
Another option would be to use Type.IsPrimitive - is that what you're looking for? If so, you should be aware that decimal, DateTime and string are not primitive types.
If you can describe exactly what makes a type an "object" in your way of thinking (or rather, in whatever way makes a semantic difference in what you're trying to do with your type). I suspect you don't currently have a very clear set of criteria - coming up with those criteria may well clarify other aspects of your current task, too.
You can use a little reflection to see if a property is a value type or a class type. Class is probably what you mean by "object". All types in .NET derive from the object type.
Client.GetType().IsClass
Or you can loop through all properties and see which are compound
foreach(var p in ProgrammeClient.GetType().GetProperties())
{
if(p.PropertyType.IsClass) Console.WriteLine("Found a class");
}
Check if the type is a string and check if it is a class.
public static bool IsNonStringClass(this Type type)
{
if (type == null || type == typeof(string))
return false;
return typeof(Type).IsClass;
}
All properties in your example return objects, as everything is an object in .NET; int and bool are objects. If you mean a reference type, as opposed to value types, then you can do the following:
foreach (PropertyInfo pi in typeof(Client).GetProperties()) {
if (pi.PropertyType.IsClass) {
// reference type
// DoMyFunkyStuff
}
}
You can enumerate the properties via Reflection, and check them:
bool ContainsOnlyValues() {
return typeof(ProgrammeClient).GetProperties().All(x => x.PropertyType.IsValueType);
}
The Type.IsvalueType property can reveal this.
Id.GetType().IsValueType
This will be True for Id, false for a class
If using TypeSupport nuget package you can simply do:
typeof(ProgrammeClient).GetExtendedType().IsReferenceType;
TypeSupport does inspection and provides deeper insight on the capabilities of a given type, handling things like strings, enums etc and makes it easier to code these types of things.
I'm using Entity Framework. I have a few database tables that store different statistics:
Stats1 (Stats1ID, Mean)
Stats2 (Stats2ID, Mean)
Stats3 (Stats3ID, Mean)
I have multiple methods which I want to consolidate into a single method. The only difference between these methods are the parameters:
public static bool IsValid(Stats1 stat, decimal value) { // }
public static bool IsValid(Stats2 stat, decimal value) { // }
// etc
The methods all use the common field of these different Stat objects - 'Mean'. How do I replace the first parameter with some generic object that I can use to access the Mean field of whichever type is passed in? Not sure if this is relevant but I use "database first" and generate the model like that
edit: appreciate the answers, will test things soon
All Stats classes can implement an interface, say IStat, containing the Mean property. It's enough to extend a generated partial class by another partial class:
partial class Stats1 : IStat { }
EF doesn't mind, as long as you don't use the interface for navigation property types (but you won't with database first).
Then you can define a generic method with a generic type constraint (where):
public static bool IsValid<T>(T stat, decimal value)
where T : IStat
{
// Example of what you could do here:
return stat.Mean > value);
}
Usage:
var valid = IsValid(stat1, 1);
EDIT - Didn't notice you're using Database First. I use this approach in code first, and it probably don't apply to you. But I leave it here in case anyone reads the question later.
You can define an interface that denoted the common field, like:
public interface IStatEntity
{
public int Mean { get; set; }
}
and implement the interface on all of the entities. Implementing an interface does not interfere with EF's mappings and doesn't mean anything to EF.
I use the same approach for having properties such as CreationTime and LastModificationTime and then setting them centrally in my DbContext.
You could use reflection to do what you want.
public static bool IsValid<TStats>(TStats stats, decimal value)
{
if (Equals(stats, null))
return false;
// Get the 'Mean' property
var propertyInfo = typeof(TStats).GetProperty("Mean");
if (Equals(propertyInfo, null))
return false;
// Get
var meanValue = propertyInfo.GetValue(stats, null) as decimal?;
// ... do what ever you want with the meanValue
return meanValue.HasValue && meanValue.Value == value;
}
Is there any way to distinguish a non-constant field and a constant field" at compile time in c#?
I am currently developing c# Code Analysis (FxCop) rules to check the developers' code for inconsistency in naming.
What I have been looking for is a way to target only constant fields. But how are they declared when compiled? Is there like a flag (I have been looking into "HasDefault", but this didn't give me much information).
I am using the FxCop-API (FxCopSdk.dll & Microsoft.Cci.dll). No Reflection is used.
Summing up: How can I distinguish a non-constant field from a constant field with Code Analysis(FxCop), and how can I target the constant.
Researchign further into the FxCop SDK you mentioned, i foudn a field, IsLiteral, which basically means a member which value is specified at compile time.
Would this work for you?
E.g
public class ClassFieldNamePrefixes : BaseIntrospectionRule
{
public ClassFieldNamePrefixes() :
base("ClassFieldNamePrefixes", "TutorialRules.TutorialRules",
typeof (ClassFieldNamePrefixes).Assembly)
{
}
public override ProblemCollection Check(Member member)
{
if (!(member.DeclaringType is ClassNode))
return this.Problems;
Field fld = member as Field;
if (fld == null)
return this.Problems;
if (fld.IsLiteral &&
fld.IsStatic &&
field.Flags.HasFlag(FieldFlags.HasDefault))
{
....
}
return this.Problems;
}
}
If I compile some assembly that contains this class
namespace Foo
{
public static class Bar
{
public int Pointless()
{
const int Whatever = 1;
return Whatever;
}
}
}
Whatever will not be accesible outside the class. I think, even using reflection. In fact, it may be simplified away in the IL (this is conjecture.)
The name of Whatever is purely a style issue and has no effect on the compiled assembly. If it were a public field, e.g.
namespace Foo
{
public static class Bar
{
public const int Whatever = 1;
}
}
then the name could be analysed by Code Analysis.
Given that public non-constant fields will already be flagged by
CA1051: Do not declare visible instance fields
CA2211: Non-constant fields should not be visible
perhaps you don't actually need to distinguish at all.
I have found a somewhat dirty way of targeting constants.
Using the following will target them (but may give false-positives):
Field field = member as Field;
if (field == null)
return null;
if (field.Flags.HasFlag(FieldFlags.HasDefault) && field.IsLiteral && Field.IsStatic)
{
// Your code here.
}
In his answer to For which scenarios is protobuf-net not appropriate? Marc mentions:
jagged arrays / nested lists without intermediate types aren't OK - you can shim this by introducing an intermediate type in the middle
I'm hoping this suggests there is a way to do it without changing my underlying code, maybe using a surrogate?
Has anybody found a good approach to serializing/deserializing a nested/jagged array
At the current time, it would require (as the message suggests) changes to your model. However, in principal this is something that that the library could do entirely in its own imagination - that is simply code that I haven't written / tested yet. So it depends how soon you need it... I can take a look at it, but I can't guarantee any particular timescale.
A solution might be to serialize an intermediate type, and use a getter/setter to hide it from the rest of your code.
Example:
List<double[]> _nestedArray ; // The nested array I would like to serialize.
[ProtoMember(1)]
private List<ProtobufArray<double>> _nestedArrayForProtoBuf // Never used elsewhere
{
get
{
if (_nestedArray == null) // ( _nestedArray == null || _nestedArray.Count == 0 ) if the default constructor instanciate it
return null;
return _nestedArray.Select(p => new ProtobufArray<double>(p)).ToList();
}
set
{
_nestedArray = value.Select(p => p.MyArray).ToList();
}
}
[ProtoContract]
public class ProtobufArray<T> // The intermediate type
{
[ProtoMember(1)]
public T[] MyArray;
public ProtobufArray()
{ }
public ProtobufArray(T[] array)
{
MyArray = array;
}
}