I was experimenting in order to create a little compile-safe helper for mapping between classes.
public class A : IMappableTo<B>, IMappableTo<A>
{
public string Name { get; set; }
}
public class B
{
public string Name { get; set; }
}
public interface IMappableTo<T>
{
}
public static class ExtensionTest
{
public static T MapTo<T>(this IMappableTo<T> source)
{
return default(T); // this does not mind, just for demo purposes
}
}
The intent was to create an extension method able to detect not implemented maps (at compile time).
It worked as expected, but with an unexpected issue.
public static void test()
{
// compiler doesn't complain, but intellisense can't autocomplete it.
var case1 = new A().MapTo<A>().MapTo<B>();
var case2 = new A().MapTo<string>(); // compiler complains, as intended
}
So well, it does compile and work, but Visual Studio (tested with 2015/2017) is unable to autocomplete the extension method. I did some additional tests and it seems to be produced by the fact that class A implements two IMappableTo constructed interfaces. If I remove one, the autocomplete simply works again.
Any idea of how to fix this behaviour or rewrite the code in a manner that cause no further troubles?
Related
I'm trying to extend a generic type class, but I can't get VS to see the extension methods.
Of course there would be many ways around this and it sure isn't best practice in all situations, but I can't figure out why, of the two apparently identical cases below, the first one works and the other doesn't.
First, an example of a successful attempt to extend the List class (just to prove I can handle the basics):
namespace Sandbox.ExtensionsThatWork
{
public static class ListExtensions
{
public static List<TheType> ExtendedMethod<TheType>(this List<TheType> original)
{
return new List<TheType>(original);
}
}
public class ExtensionClient
{
public void UseExtensionMethods()
{
List<string> a = new List<string>();
List<string> b = a.ExtendedMethod();
}
}
}
However, the object I want to extend is something like this
namespace Sandbox.Factory
{
public class Factory<T>
{
public static Thing<T> Create()
{
return new Thing<T>();
}
}
public class Thing<T>{}
public static class FactoryExtensions
{
internal static Thing<FactoryType> CreateFake<FactoryType>(this Factory<FactoryType> original)
{
return new FakeThing<FactoryType>();
}
}
public class FakeThing<T> : Thing<T>{}
}
And in this case I can't for the life of me get the compiler to see the extension method.
namespace Sandbox.FactoryClients
{
public class FactoryClient
{
public void UseExtensionMethods()
{
Factory.Thing<int> aThing = Factory.Factory<int>.Create();
///THE COMPILER WON'T FIND THE CreateFake METHOD
Factory.Thing<int> aFakeThing = Factory.Factory<int>.CreateFake<int>();
}
}
}
What am I missing?
Thank you all for your time.
Your problem has nothing to do with generics.
You're calling the extension as if it were a static method of Factory.Factory<int>, which it cannot be.
C# does not support extension static methods (meaning extension methods that act like static methods of the type of the this parameter) on any type.
You need an instance to call the extension method on (like you do in your "working" example):
using Sandbox.Factory;
public void UseExtensionMethods()
{
Thing<int> aThing = Factory<int>.Create();
Thing<int> aFakeThing = new Factory<int>().CreateFake();
}
I have a bunch of classes that formulate various variations of items. I currently have a class like this:
public class Item {
public ItemFile file { get; set;}
public ItemCalendar calendar { get; set;}
public ItemWebsite website { get; set;}
}
ItemFile etc are classes made using Entity Framework and map to the database tables that provide the information relating to that type of item. The item class only has one of the internal properties actually instantiated.
I can see the number of items growing to around 25 or more. I don't feel right making the view model containing 25 properties where 24 of them are null with only one being not null.
I want something that can work with entity framework and return a class that can return only it's actual type. Therefore if I ask for the variation of the item I would get back ItemFile for files and ItemCalendar for calendars.
I've tried something like this:
public class Item
{
public ItemBase item { get; set; }
}
public class ItemBase
{
public Type typeName { get; set; }
public object ItemInstance { get; set; }
public typeName GetInstance()
{
return Convert.ChangeType(ItemInstance, typeName);
}
}
But then I don't know how to return ItemFile as public typeName is an error.
I then tried:
public class Item
{
public ItemBase<ItemFile> item { get; set; }
}
public class ItemBase<T>
{
public T ItemInstance { get; set; }
}
But to get that to work, I had to hardcore FileItem in the <> on the item class which goes back into knowing the type before hand.
Is there anyway to get this to work? Bonus points if it can work with entity framework as I'm pulling back the classes from there. Worst comes to worst if it doesn't work entity framework wise is I can pull it all and then convert it into the form that answers the question.
If the title of the question is wrong, feel free to edit. I wasn't sure how to ask.
tl;dr version: I want to be able to return multiple types of classes from a function using a type that is passed in not using <>.
Edit 1:
I forgot to show my inheritence example. I've tried this but also got stuck with something similar to the above.
public class ItemBase
{
public Type typeName { get; set; }
public object ItemInstance { get; set; }
public typeName GetInstance()
{
return Convert.ChangeType(ItemInstance, typeName);
}
}
public class ItemFile : ItemBase
{
public String FileName { get; set; }
}
public class Test
{
public void testFunction()
{
//Made this just so the compiler didn't complain.
ItemFile testFile = new ItemFile();
//I can use a function to get the item base.
ItemBase baseItem = testFile;
//How do I do this? Use a function to get the ItemFile from the instance.
ItemFile finalItem = baseItem.GetInstance();
}
}
I want to be able to return multiple types of classes from a function using a type that is passed in not using <>.
<> (generics) are the mechanism by which a function can explicitly return more than one type. Without generics the function returns whatever type it says it returns.
object SomeFunction() // Returns an object
ItemBase SomeOtherFunction () // returns ItemBase
In the above examples, SomeFunction can still return any type (because all types inherit from object.) But it won't be explicit. All you know for sure is that it's an object.
Similarly, SomeOtherFunction can return an ItemBase or any class that inherits from ItemBase. But that's all you know about it.
Ideally you don't want to have functions returning one type (like object or ItemBase) and then cast the result of the function to another more specific type. The function should return what you want, and you should want what the function returns. Generics help with that. For example:
public TItem Instance<TItem>() where TItem : ItemBase
allows a function to return a specified type as long as it is an ItemBase or inherits from one.
This last comment is going to seem odd or useless but it's the truth. If you find yourself in a scenario where the above rules don't work and you need to be able to do something that you can't do or shouldn't do, go back and rethink why you're trying to do that. That's where the real problem is.
That means you probably need to go back a step and get yourself out of the situation where you're trying to work against the language. What are you trying to accomplish and how can you do it in a way that works with the language, not against it?
I believe this is about as close as you're going to get.
using System;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
EFTypeData itemData = GetItemData();
var asmName = Assembly.GetExecutingAssembly().GetName().Name;
var type = Type.GetType($"ConsoleApplication1.{itemData.TypeName}, {asmName}");
var instance = Activator.CreateInstance(type);
var item = new Item<Object>()
{
ItemBase = instance
};
}
private static EFTypeData GetItemData()
{
return new EFTypeData() { TypeName = "ItemFile" };
}
}
class EFTypeData
{
public string TypeName { get; set; }
}
class Item<T> where T: class
{
public T ItemBase { get; set; }
}
class ItemFile
{
public string FileName { get; set; }
}
}
This will, given a string "ItemFile", create an instance and assign it to Item. If you run this and inspect item, you have
The big caveat to this is that at compile-time, all you have is an Object as your ItemBase. And without hard-coding your Type (i.e. var item = new Item<ItemFile>();), you're never going to know more.
That said, with this method you are perfectly clear to iterate over fields and such using Reflection. But this is a limitation of this level of run-time object manipulation.
is it possible to call properties after methods?
Example:
public static class Test
{
public static string Show { get; set; }
public static void Get(string s)
{
Show = s;
}
}
and call like this:
Test.Get("HI").Show;
Update 2: A fluent interface
If you are implementing a fluent interface, I would suggest renaming your methods as such:
public class Test
{
public string Show { get; set; }
public Test ConfigureShow(string show)
{
Show = show;
return this;
}
}
Your method is much more readable now and clearly defines the intent of the method:
var test = new Test()
.ConfigureShow("HI");
Make the rest of the methods in your class follow the same pattern and chain your methods on new lines for improved readability.
Update 1: What is your intent?
Is there a particular reason that you are trying to do this? There are several issues with your class:
Your methods should make sense - you should not have a method called Get which takes a parameter and then modifies the object. Generally Get methods imply that you are simply fetching something from the object.
Why are you passing in a parameter to the method, only to fetch it again?
Are you trying to implement a Fluent interface?
What is wrong with:
var show = "HI";
var test = new Test();
test.Show = show;
//You already have your text in the variable show, so why do you want to access it again?
Original answer to OP's question
public class Test
{
public string Show { get; set; }
public Test Get(string s)
{
Show = s;
return this;
}
}
I`m using Castle.Windsor library, and what i want is to get "Implementation" property, from all items in IRegistration[].
I have following interfaces and classes:
public interface IA
{
int a { get; set; }
}
public class A : IA
{
public int a { get; set; }
}
public interface IB
{
int b { get; set; }
}
public class B : IB
{
public int b { get; set; }
}
And a static class which contains this Components:
public static class Bootekstraperek
{
private static readonly IRegistration[] _commonRegistrations =
{
Component.For<IA>().ImplementedBy<A>(),
Component.For<IB>().ImplementedBy<B>()
};
public static void Test()
{
List<IRegistration> list = _commonRegistrations.ToList();
foreach (var registration in list)
{
ComponentRegistration a = registration as ComponentRegistration;
Console.WriteLine(a.Implementation.FullName);
}
}
}
And of course variable a is null after every iteration.
It works only when i cast to Generic ComponentRegistration
var a = registration as ComponentRegistration<A>;
But, that dont helps me if i have too much different components inside this array. So Switch statement is not an option.
I have tried using reflections, but i still didn`t managed to properly cast.
How can i achieve what i want With or Without using reflections?
thxia.
This is not easy because the IRegistration API was never meant to be used in this way.
So my answer has two parts.
How you can do it. Use dynamic.
you only need to change a small bit of your code:
foreach (dynamic registration in list)
{
Console.WriteLine(registration.Implementation.FullName);
}
What is the underlying goal you're trying to achieve here? Have a look at Windsor's diagnostics if your goal is to keep a level of visibility into what gets registered, how and be on a lookout for potential issues.
A small amount of Reflection solves the problem (it is a small amount, but it looks verbose, because Reflection):
foreach (var registration in list)
{
Console.WriteLine(
((Type)registration.GetType().GetProperty(
"Implementation"
).GetGetMethod().Invoke(
registration,new object[] { })
).FullName);
}
Since you won't know the types that are being used as generic type parameters until runtime, I don't think there's a way to do this without any Reflection.
The above assumes that all of the registrations will be ComponentRegistration<T> objects of some sort. If that's an unsafe assumption, there may be some other implementations of IRegistration that don't implement an Implementation property or it may not be publicly accessible - so insert appropriate interim error checking if that's the case.
I have the following code. I expect it to print:
A
B
C
DONE
instead it prints
P
P
P
DONE
why?
UPDATE
I'm not asking for a work around solution. I want to know why this is happening. I thought generics were resolved at compile time. From what I can tell it should be able to resolve these to the proper methods at compile time, but apparently it is not and I do not understand why. I am looking for an explanation of why, not a work around solution.
here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication50
{
class Parent
{
public string FieldName { get; set; }
public string Id { get; set; }
}
class ChildA : Parent
{
public string FieldValue { get; set; }
}
class ChildB : Parent
{
public DateTime? Start { get; set; }
public DateTime? End { get; set; }
}
class ChildC : Parent
{
public ICollection<string> Values { get; set; }
}
class Program
{
void Validate<T>(Parent item) where T : Parent
{
if (item is T)
Validate(item as T);
}
void Validate(ChildA filter)
{
Console.WriteLine("A");
}
void Validate(ChildB filter)
{
Console.WriteLine("B");
}
void Validate(ChildC filter)
{
Console.WriteLine("C");
}
void Validate(Parent filter)
{
Console.WriteLine("P");
// do nothing placeholder so the code will compile
}
ArgumentException Fail(Parent filter, string message)
{
return new ArgumentException(message, filter.FieldName);
}
void Run()
{
var list = new List<Parent> {
new ChildA(), new ChildB(), new ChildC() };
Validate<ChildA>(list[0]);
Validate<ChildB>(list[1]);
Validate<ChildC>(list[2]);
}
public static void Main()
{
new Program().Run();
Console.WriteLine();
Console.WriteLine("DONE");
Console.ReadLine();
}
}
}
Generics are a run-time concept. This is their primary difference from C++ templates, which are a compile-time concept.
Within the method Validate<T>, T is always unknown at compile-time, even when explicitly specified by the caller. The only thing Validate<T> knows about T is that it descends from Parent.
More specifically, generics cannot be used to generate code. What you're trying would work under C++ because when C++ sees a call to Validate<ClassA>, it actually recompiles Validate<T>, so templates become a kind of code generation. Under C#, Validate<T> is only compiled once, so generics cannot be used as a kind of code generation.
Under C++, the call to Validate<ClassA> will instantiate the template at compile-time.
Under C#, the call to Validate<ClassA> will instatiate the generic method at run-time.
Overload resolution is performed at compile-time, not at runtime.
The usual solution is to use simple virtual dispatch here:
class Parent
{
public virtual void Validate() { Console.WriteLine("P"); }
}
class ChildA : Parent
{
public override void Validate() { Console.WriteLine("A"); }
}
class ChildB : Parent
{
public override void Validate() { Console.WriteLine("B"); }
}
void Run()
{
var list = new List<Parent> { new ChildA(), new ChildB() };
list[0].Validate(); // prints "A"
list[1].Validate(); // prints "B"
}
The item will ALWAYS be validated as type Parent.
The idea behind generics is that you do NOT have type specific code.. hence the "generic" part of it.
You are limiting to a branch of classes, in this case Parent and everything that descends from it. This means the code should execute as if the object being passed in was of type Parent.
As dtb said, the Visitor pattern could apply here.
Another idea would be to simply have an interface which defined the Validate() method that each class had to support. I think this would be a better route to take.
Assuming you can use C# 4.0, you can defeat the static overload resolution that the C# compiler will do by using the "dynamic" keyword. Simply change your validate function to:
void Validate<T>(Parent item) where T : Parent
{
dynamic dyn = item;
if (item is T)
Validate(dyn);
}
and the output will be:
C:\tmp>temp.exe
A
B
C
DONE
I just learned this myself from #juharr's link to Eric Lippert's blog. Read more about the dynamic type on msdn.