Every InfringementEntity has a type.
foreach (InfringementEntity ie in _infCol.InfCollection.Select(r=>r).Distinct())
{
InfringementLodgementEntity.InfringementCollection.InfCollection.Add(ie);
}
InfringementLodgementCollection.InfringementLodgementEntities
.Add(InfringementLodgementEntity);
I need to select all Infringement Entity with a different type and insert them in a new InfringementLodgementEntity. And then add this InfringementLodgementEntity in InfringementLodgementCollection.
Question is how would I select infringementEntity with different types add them in a new InfringementLodgementEntity.
You should implement an IEqualityComparer<InfringementEntity> checking for the type, and use the Distinct overload that is accepting such a comparer.
If I understand your question, you can use OfType().
var theInfringementEntitiesYouWant = _infCol.InfCollection.OfType<TheTypeYouWant>().Distinct();
I left out .Select(r=>r) because it wasn't doing anything useful.
public abstract class BaseClass
{
private Type _classType;
public Type ClassType
{
get
{
return _classType;
}
set
{
_classType= value;
}
}
public abstract Type GetType();
}
public class InheritedClass: BaseClass
{
public override Type GetType()
{
if (ClassType == null)
{
ClassType = typeof(InheritedClass);//ie SingleInfringement or DblInfringment
}
return ClassType;
}
}
The simplest way I've found to deal with this is just have an abstract method GetType() in your base class which by definition must be overridden in your inherited class.
Reflection is rather expensive and should be used sparingly in most cases. So when we do use it we just store the result of our reflection.
This then allows us to do:
var entities = _infCol.InfCollection.Where(w => w.GetType() == typeof(DesiredType) );
from here you can do what you want, a bulk insert into another collection or whatever.
Related
I have about 1000 classes in which i need to count the number of properties of. I have the following code:
public static int NumberOfProperties()
{
Type type = typeof(C507);
return type.GetProperties().Count();
}
I could copy and paste this in to each class changing the typeof parameter but this seems a bit tedious.
Is there anyway to make an extensions method to do this by just doing var nop = C507.NumberOfProperties();?
Just to add to the answers suggesting an extension for object for completeness: you can also consider implementing an extension only for Type:
public static int GetPropertyCount(this Type t)
{
return t.GetProperties().Length;
}
and use it like this:
typeof(C507).GetPropertyCount();
The advantage is that you can get the number of properties directly from the type and do not have to create an instance first.
So you can write an extension method that uses object or one that uses type.
public static class ObjectExtensions
{
public static int GetNumberOfProperties(this object value)
{
return value.GetType().GetProperties().Count();
}
public static int GetNumberOfProperties(this Type value)
{
return value.GetProperties().Count();
}
}
Usage:
new C507().GetNumberOfProperties();
typeof(C507).GetNumberOfProperties();
However, you explicitly state two things:
I could copy and paste this in to each class changing the typeof
I have about 1000 classes
You'll likely not want to instantiate a 1000 classes or copy and paste typeof() 1000 times
In this case, you will want to read them all from the Assembly.
So something like:
typeof(SomeClass).Assembly.GetTypes().Select(x => new
{
x.Name,
PropertyCount = x.GetType().GetProperties().Count()
});
Where SomeClass is a class (doesn't matter which) where all the classes reside.
I just simply select them out into an anonymous object which contains the Types name and property count.
This:
typeof(SomeClass).Assembly
Is just a convience way to get the assembly. There are other ways.
Assembly.GetAssembly(typeof(Program)).GetTypes()
Assembly.GetCallingAssembly().GetTypes()
Assembly.Load("Some Assemble Ref").GetTypes()
You can do allsorts with the types that you find. If you select out the Type itself, you can instantiate it later using Activator.CreateInstance (if it has parameterless constuctor). You can also auto fill the properties with reflection as well.
It is impossible to have a static extension method as you imagine it. That being said, it would be possible to create a generic method in a helper class as follows.
public static int NumberOfProperties<T>()
{
Type type = typeof(T);
return type.GetProperties().Count();
}
Given a type SomeType it could be called as int n = NumberOfProperties<SomeType>().
You could make an extension method on object like this:
public static int PropertyCount(this object thing)
{
return thing.GetType().GetProperties().Count();
}
And use it on any object you like:
var x = "some string";
var numProps = x.PropertyCount();
If you want to have an extension method on object:
public static ObjectExtensions
{
public static int NumberOfProperties(this object value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetType().GetProperties().Length;
}
}
...
C507 myObj = new C507();
// How many properties does myObj instance have?
int propCount = myObj.NumberOfProperties();
If you want to have an extesnion method on Type:
public static TypeExtensions
{
public static int NumberOfProperties(this Type value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetProperties().Length;
}
}
...
// How many properties does C507 type have?
int propCount = typeof(C507).NumberOfProperties();
There are a couple of ways to do this that are variations of the same thing.
You can pass the Type as an argument to a method:
public static class Helper {
public static int NumberOfProperties(Type type)
{
return type.GetProperties().Count();
}
}
Which you would call like this:
// Imagine you have a class called MyClass
var result = Helper.NumberOfProperties(typeof(MyClass));
You use use the generic system in C# to make the syntax a little cleaner. That would look like this:
public static class Helper {
// Notice the argument was removed and
// the use of the "generic" syntax <T>
public static int NumberOfProperties<T>()
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
And you would call it like this:
var result = Helper.NumberOfProperties<MyClass>();
You could also use "Extensions" which allow you to call it as if it was a method that belonged to your classes.
public static class Helper {
// notice the `this` keyword before the parameter
// this is what tells C# that this is an extension method
public static int NumberOfProperties<T>(this T #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
This will allow you to call the method like this:
var instance = new MyClass();
var result = instance.NumberOfProperties();
In this example I used the generic syntax so that it applies to any type of object. If you wanted to limit it to only objects that inherit from a specific interface or base class you would just change it from using the generic syntax to using the base class/interface. Like this:
public static class Helper {
// notice the type got changed from a generic <T>
// to specifying the exact class you want to "extend"
public static int NumberOfProperties(this MyBaseClass #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
As #rené-vogt mentioned you can also create the extension method so that it extends the type Type instead. See his answer in this thread: https://stackoverflow.com/a/38455233/984780
You can make a generic extension method which can apply to all types:
public static int PropertyCount<T>(this T obj)
{
return typeof(T).GetProperties().Length;
}
This will apply to all types including value types (I.E. structs) which applying to object will not. Thanks to piedar for pointing out my mistake here, applying to object does still add this extension method to value types.
If your classed can implement an interface, then you can extend that interface.
public interface IExtensible {
}
class C507 : IExtensible {
}
public static int NumberOfProperties(this IExtensible extensible)
{
Type type = extensible.GetType();
return type.GetProperties().Count();
}
That being said, having hundreds of (generated?) classes looks like a bad solution to begin with.
I have a class which uses generic properties. For example:
class Person
{
public MyGenericProperty<string> Field1
{
get { return field1; }
set { field1 = value; }
}
private MyGenericProperty<string> field1= new MyInheritedGenericProperty<string>("Alan1");
}
I want to use this class with reflection at another class and i have a method like that
public void DoSomethingWithProperty(object sourceobject)
{
foreach (var aProperty in sourceobject.GetType().GetProperties())
{
*if(aProperty.PropertyType == typeof(MyGenericProperty<>))*
{
*var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);*
}
}
return null;
}
I have two problem
1- How can do type check of generic property. In that example code of if(aProperty.PropertyType == typeof(MyGenericProperty<>)) does not work.
2- T of MyGenericProperty could be any class and how can cast MyGenericProperty class without knowing T by reflection as
var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);
Thank for helps.
Firstly, it's important to understand that you don't have a "generic property" - there's no such thing. You have a property whose type is a generic type... and that's not the same thing. (Compare that with a generic type or a generic method, each of which is genuinely generic in terms of introducing new type parameters.)
You can test it using this code:
if (aProperty.PropertyType.IsGenericType &&
aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))
But as for the casting - it depends on what you want to do with the value afterwards. You may want to declare a non-generic base type of MyGenericProperty<> containing all the members which don't depend on the type parameter. I'd typically give that the same name as the generic type (e.g. MyGenericProperty) just without giving it type parameters. Then if you only need one of those members, you can use:
if (aProperty.PropertyType.IsGenericType &&
aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))
{
var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
// Use value
}
But then in that case you could use Type.IsAssignableFrom anyway:
if (typeof(MyGenericProperty).IsAssignableFrom(aProperty.PropertyType))
{
var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
// Use value
}
If these hints don't help you, please give more details of what you're trying to do.
I have a series of static methods to modify a collection then return the modified collection:
private static IEnumerable<Invoice> ResolveProxies(IEnumerable<Invoice> e) {
// do something to e
return e;
}
private static IEnumerable<Person> ResolveProxies(IEnumerable<Person> e) {
// do something to e
return e;
}
In another part of the application there is a method to decide if a collection is of a certain type, so that it can be converted to that type and have its corresponding ResolveProxies method called:
public static GridModel<T> ToGridModel<T>(this GridModel gridModel) {
// gridModel.Data is just IEnumerable
var collection = gridModel.Data as IEnumerable<T> ?? new List<T>();
return new GridModel<T> {
Data = EvaluateDynamicProxies(collection),
Total = gridModel.Total
};
}
private static IEnumerable<T> EvaluateProxies<T>(IEnumerable<T> collection) {
if (collection is IEnumerable<Invoice>) {
var enumeration = (collection as IEnumerable<Invoice>);
return ResolveProxies(enumeration) as IEnumerable<T>;
}
if (collection is IEnumerable<Person>) {
var enumeration = (collection as IEnumerable<Person>);
return ResolveProxies(enumeration) as IEnumerable<T>;
}
// proxy resolution isn't needed so return the unchanged collection
return collection;
}
Having such repetitive conditional logic is bad code smell. I'm struggling to come up with some way to mark particular types so that I know they have a corresponding proxy resolver method. Something like this perhaps:
public interface IProxyResolver<out T> where T:IEnumerable<T> {
T ResolveProxies();
}
But how would I use this? In effect I need a way to ask the compiler:
Does T have a matching ResolveProxies method?
What is the name of the class or method that resolves proxies for T so that I can get an instance of it and call it?
You could use an inversion of control (IOC) framework. For example, my team uses Castle Windsor. You can register services (usually interfaces) and types that provide the services. It has some nice generics resolution, so you can do things like this:
interface IProxyResolver<T> { /* whatever */ }
class ProxyResolver<T> : IProxyResolver<T> { /* ... */ }
class PersonProxyResolver : ProxyResolver<Person> { }
class InvoiceProxyResolver : ProxyResolver<Invoice> { }
then, you can summon these types like this:
void SomeMethodThatNeedsAProxyResolver<T>(T obj)
{
var resolver = ioc.Resolve<IProxyResolver<T>>();
//...
}
If you've regsitered the classes above, when T is Person or Invoice, you get the correct non-generic subclass of ProxyResolver; if it is any other type, you get the default generic superclass. Of course, you can structure things differently; if you need a specific proxy resolver for every type, that's possible too.
How about using a custom attribute? This is how custom serializers are selected, etc.
You'd start by defining the Attribute class:
public class ProxyResolverAttribute : Attribute {
public Type ResolverType { get; set; }
public ProxyResolver(Type resolverType) { ResolverType = resolverType; }
}
and then put that on the type contained, e.g.
[ProxyResolver(TypeOf(InvoiceProxyResolver))]
public class Invoice ... { ... }
then use reflection to see if the generic type used in the collection specifies a proxy resolver type:
// Untested, beware of bugs
var enumerationGenericType = enumeration.GetType().GetGenericArguments().FirstOrDefault();
var resolverAttribute = enumerationGenericType.GetType().GetCustomAttributes(TypeOf(ProxyResolverAttribute)).FirstOrDefault();
if (resolverAttribute != null) {
var resolverType = resolverAttribute.ResolverType;
// instanciate something of resolverType here
}
EDIT: Reading the comments, if you don't want to apply the attributes to the contained objects, I'd suggest creating custom classes which inherit List and apply the attribute there, e.g.
[ProxyResolver(TypeOf(InvoiceProxyResolver))]
public class InvoiceList : List<Invoice>
I need some help figure out how to use reflection to get the concrete implementation based of the Dto type:
public interface IDocumentService<TDto>
{
}
public interface ICommentService: IDoumentService<CommentDto>
{
}
public abstract class DocumentService<TEntity,TDto>: IDocumentService<TDto> where TEntity: Entity, where TDto: Dto
{
}
public class CommentService: DocumentService<Comment,CommentDto>, ICommentService
{
}
So, what I want to do, is pass the CommentDto to a method so I can get to the CommentService.
public IDocumentService<TDto> GetDocumentService<TDto>()
{
//based on the TDto type I want to find the concrete that
//implements IDocumentService<TDto>
}
I would call it like this:
var commentDocumentService = GetDocumentService<CommentDto>();
So, I would get back CommentService, knowing that I would only see the methods part of the IDocumentService interface.
Here is a possible implementation for GetDocumentService.
public static IDocumentService<TDto> GetDocumentService<TDto>()
{
// Gets the type for IDocumentService
Type tDto=typeof(IDocumentService<TDto>);
Type tConcrete=null;
foreach(Type t in Assembly.GetExecutingAssembly().GetTypes()){
// Find a type that implements tDto and is concrete.
// Assumes that the type is found in the executing assembly.
if(tDto.IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface){
tConcrete=t;
break;
}
}
// Create an instance of the concrete type
object o=Activator.CreateInstance(tConcrete);
return (IDocumentService<TDto>)o;
}
It wasn't clear whether you wanted to return a new object, so I assumed so.
EDIT:
Due to your comment, here is a modified version of GetDocumentService. The disadvantage is that you need to specify another type parameter. The advantage, though, is that this approach provides a certain degree of type safety, since both type parameters must be compatible.
public static T GetDocumentService<TDto, T>() where T : IDocumentService<TDto>
{
// Gets the type for IDocumentService
Type tDto=typeof(T);
Type tConcrete=null;
foreach(Type t in Assembly.GetExecutingAssembly().GetTypes()){
// Find a type that implements tDto and is concrete.
// Assumes that the type is found in the calling assembly.
if(tDto.IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface){
tConcrete=t;
break;
}
}
// Create an instance of the concrete type
object o=Activator.CreateInstance(tConcrete);
return (T)o;
}
EDIT 2:
If I understand correctly, you want to get the other interfaces implemented by the type of the return value of GetDocumentService. For example, GetDocumentService<CommentDto> returns an object of type CommentService that implements the ICommentService interface. If I understand correctly, the return value should be a Type object (for example, the return value could be typeof(ICommentService)). Once you have the type, you should call the type's FullName property to get the type's name.
Use the following method on the return value of GetDocumentService to get the type of interface implemented by that value, for instance, typeof(ICommentService).
public static Type GetDocumentServiceType<TDto>(IDocumentService<TDto> obj){
Type tDto=typeof(IDocumentService<TDto>);
foreach(Type iface in obj.GetType().GetInterfaces()){
if(tDto.IsAssignableFrom(iface) && !iface.Equals(tDto)){
return iface;
}
}
return null;
}
Firstly, your CommentService class needs to be discoverable somehow, given the type of TDto. You can search all the loaded types from all the assemblies in the current AppDomain - however that will be painfully slow.
So you have the following viable options:
Use an attribute on the assembly that defines CommentService.
Use configuration to define this information.
Use MEF.
I'll demonstrate the first approach. Firstly create the attribute:
[AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = true)]
public sealed class DtoProviderAttribute : Attribute
{
public Type ProvidedType { get; private set; }
public Type ProviderType { get; private set; }
public DtoProviderAttribute(Type providedType, Type providerType)
{
ProvidedType = providedType;
ProviderType = providerType;
}
}
And then apply it to the assembly that defines CommentService (typically you would put in AssemblyInfo.cs).
[assembly:DtoProvider(typeof(CommentDto), typeof(CommentService))]
Now you can use those attributes to search for the concrete implementations.
public class ServiceFactory
{
private static readonly Dictionary<RuntimeTypeHandle, Func<object>> _dtoMappings = new Dictionary<RuntimeTypeHandle, Func<object>>();
public static IDocumentService<TDto> GetDocumentService<TDto>()
{
var rth = typeof(TDto).TypeHandle;
Func<object> concreteFactory;
lock (_dtoMappings)
{
if (_dtoMappings.TryGetValue(typeof(TDto).TypeHandle, out concreteFactory))
return (IDocumentService<TDto>)concreteFactory();
FillMappings();
if (!_dtoMappings.TryGetValue(typeof(TDto).TypeHandle, out concreteFactory))
throw new Exception("No concrete implementation found.");
return (IDocumentService<TDto>)concreteFactory();
}
}
private static void FillMappings()
{
// You would only need to change this method if you used the configuration-based approach.
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var attrs = assembly.GetCustomAttributes(typeof(DtoProviderAttribute), false);
foreach (DtoProviderAttribute item in attrs)
{
if (!_dtoMappings.ContainsKey(item.ProvidedType.TypeHandle))
{
var expr = Expression.Lambda<Func<object>>(Expression.Convert(Expression.New(item.ProviderType), typeof(object)));
_dtoMappings.Add(item.ProvidedType.TypeHandle, expr.Compile());
}
}
}
}
}
As 'Rune' pointed out: because of the cache the overhead of searching all the assemblies is low:
private static void FillMappings()
{
foreach (var type in AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()).Where(x => x.IsClass && !x.IsAbstract))
{
foreach (var iface in type.GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDocumentService<>)))
{
var arg = iface.GetGenericArguments()[0];
if (!_dtoMappings.ContainsKey(arg.TypeHandle))
{
var expr = Expression.Lambda<Func<object>>(Expression.Convert(Expression.New(type), typeof(object)));
_dtoMappings.Add(arg.TypeHandle, expr.Compile());
}
}
}
}
another possibility:
public IDocumentService<TDto> GetDocumentService<TDto>()
{
var genericParameter = typeof(TDto);
return (from type in Assembly.GetExecutingAssembly().GetTypes() // Get Types
where type.GetConstructor(Type.EmptyTypes) != null // That is concrete
let interfaces = type.GetInterfaces()
from intf in interfaces
where intf.IsGenericType // Which implement generic interface
let genarg = intf.GetGenericArguments()[0]
where genarg == genericParameter // Where generic argument is of type genericParameter
select (IDocumentService<TDto>) // Cast to IDocumentService
Activator.CreateInstance(type)).FirstOrDefault(); // Instantiate
}
I'm trying to do this:
public interface IVirtualInterface{ }
public interface IFabricationInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public interface ICoatingInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public class FabInfo : IFabricationInfo
{
public int Requirement
{
get { return 1; }
set { }
}
public int Type
{
get {return 1;}
set{}
}
}
public class CoatInfo : ICoatingInfo
{
public int Type
{
get { return 1; }
set { }
}
public int Requirement
{
get { return 1; }
set { }
}
}
public class BusinessObj
{
public T VirtualInterface<T>() where T : IVirtualInterface
{
Type targetInterface = typeof(T);
if (targetInterface.IsAssignableFrom(typeof(IFabricationInfo)))
{
var oFI = new FabInfo();
return (T)oFI;
}
if (targetInterface.IsAssignableFrom(typeof(ICoatingInfo)))
{
var oCI = new CoatInfo();
return (T)oCI;
}
return default(T);
}
}
But getting a compiler error: Canot convert type 'GenericIntf.FabInfo' to T
How do I fix this?
thanks
Sunit
Assuming all IVirtualInterface implementations will have a default constructor (as in your example), you can do this instead:
public T VirtualInterface<T>() where T : IVirtualInterface, new()
{
return new T();
}
Simples!
EDIT:
Exactly what you're trying to achieve is difficult to determine from the code you've posted. Why isn't VirtualInterface static (implies all business objects inherit this method which seems odd)? If you need o be able to parameterised constructors for your IVirtualInterface implementations, where would those parameter values come from (you're not passing any into the VirtualInterface method)?
If you just want to avoid cluttering up intellisense (a poor reason for trying something like this IMHO) but also want to maintain support for parameteried constructors, then how about this:
public T VirtualInterface<T>(Func<T> constructor) where T : IVirtualInterface
{
return constructor();
}
With usage:
IFabricationInfo fabInfo =
new BusinessObj().VirtualInterface<IFabricationInfo>(() => new FabInfo());
Overall though, and without enough information to make a solid judgement, I'd have to say that this smells.
The fact that T and FabInfo both implement IVirtualInterface does not mean you can perform a cast between the two types. For example if T is CoatInfo, then it is not compatible type with FabInfo.
Interfaces allow you to treat different objects as similar types based on the methods they provide. However, this does not mean that you can perform casts between these two types as their actual implementation can vary greatly.
Edit: After re-reading your method again, I see that you are checking the type first. The problem is that the compiler doesn't know you are performing that logic before you try to make that cast. If you are writing a generic method and are checking the type of T, you are likely misusing the concept of generics. See the other answers for the way you should be creating new instances of T.
You can get around this error by first casting to object before casting to T e.g.
return (T)(object)oFI;
and similarly for CoatInfo
However I think switching on a generic type is an abuse, since if you want a limited number of possible return values, you could make the options explicit e.g.
public IFabricationInfo GetFabricationInfo()
{
return new FabInfo();
}