How can I create a custom generic linq filter that will check if the generic class contains a property name and returns the query...
I have something like:
public static IQueryable<T> GetAllByType<T>(
this IQueryable<T> customQuery, string seller) where T : class, new()
{
customQuery = customQuery.Where(i => i.GetType().Name == "TypeOfSeller");
return customQuery;
}
If the property type on the table T exists then I want to filter the expression using the string seller passed in as a parameter...
simply: return an expression which will filter this table by the seller param which could be "big", "small" etc.
I think this does what you describe.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Seller
{
public string Name { get; set; }
public string TypeOfSeller { get; set; }
}
class SomeOtherData
{
public string Name { get; set; }
}
static class Program
{
static void Main(string[] args)
{
List<Seller> sellers = new List<Seller>();
sellers.Add(new Seller() { Name = "A", TypeOfSeller = "Test" });
sellers.Add(new Seller() { Name = "B", TypeOfSeller = "Test" });
sellers.Add(new Seller() { Name = "C", TypeOfSeller = "Other" });
var q = from p in sellers.AsQueryable<Seller>().GetAllByType("Test") select p;
List<SomeOtherData> other = new List<SomeOtherData>();
other.Add(new SomeOtherData() { Name = "A" });
other.Add(new SomeOtherData() { Name = "B" });
other.Add(new SomeOtherData() { Name = "C" });
var q2 = from p in other.AsQueryable<SomeOtherData>().GetAllByType("Test") select p;
foreach (var x in q)
Console.WriteLine(x.Name + ", " + x.TypeOfSeller);
Console.WriteLine("Other Data: ");
foreach (var x in q2)
Console.WriteLine(x.Name);
Console.ReadLine();
}
public static IQueryable<T> GetAllByType<T>(this IQueryable<T> customQuery, string seller) where T : class, new()
{
var prop = typeof(T).GetProperty("TypeOfSeller");
if(prop != null)
customQuery = customQuery.Where(i => prop.GetValue(i, new object[] {}).ToString() == seller);
return customQuery;
}
}
}
The output is:
A, Test
B, Test
Other Data:
A
B
C
I would refactor it a bit so that there's no "if" involved but that I'm only sending the entities that qualify to the method.
The next thing you want to consider is that if there are multiple entity models that share a property name and you want to share logic regarding that property name, utilize the partial aspect of the code-generated classes to extend those classes and have each of them implement an interface.
interface ISeller
{
string TypeOfSeller { get; set; }
}
This will allow you to add the interface to the list of constraints on the method and also allow you to simply utilize the TypeOfSeller property directly without trying to resort to other methods (such as reflection).
The question is not very clear but sounds like you want something like this
public static IQueryable<T> GetAllByType<T>(
this IQueryable<T> customQuery, string seller) where T : class, new()
{
return from i in customQuery
let prop = typeof(T).GetProperty("SellerType")
where prop != null && prop.GetValue(i, null).Equals(seller)
select i;
}
Related
Instead of T (Type) if I use class name i.e. sampleclass this code works properly,
but if I use T, then it shows that
'T' does not contain a definition for 'TimeStamp' and no accessible
extension method 'TimeStamp' accepting a first argument of type 'T'
could be found (are you missing a using directive or an assembly
reference?)
//Get collection.
var collection = this.GetDatabaseConnection().GetCollection<T>
(collectionName);
//filter to read specific data.
var filter = Builders<T>.Filter.Where(result => result.TimeStamp >=
startTime && result.TimeStamp <= endTime);
List < T > queryData = collection.Find<T>(filter, null).ToList();
Previously it was as follows and working finely:
//Get collection.
var collection = this.GetDatabaseConnection().GetCollection<Sampleclass>.
(collectionName);
//filter to read data using specific timestamp.
var filter = Builders<Sampleclass>.Filter.Where(result =>
result.TimeStamp >=
startTime && result.TimeStamp <= endTime);
List < Sampleclass > queryData = collection.Find<Sampleclass>
(filter, null).ToList();
i would do it using a base class like this
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System;
using System.Linq;
namespace StackOverflow
{
public class Program
{
public class Entity
{
[BsonId]
public ObjectId Id { get; set; }
public DateTime TimeStamp { get; set; }
}
public class Sample : Entity
{
public string Something { get; set; }
}
private static void Main(string[] args)
{
var collection = new MongoClient("mongodb://localhost:27017")
.GetDatabase("Test")
.GetCollection<Entity>("Samples");
var sample = new Sample
{
Id = ObjectId.GenerateNewId(),
Something = "something",
TimeStamp = DateTime.UtcNow
};
collection.InsertOne(sample);
var result = collection.AsQueryable()
.Where(s =>
s.TimeStamp >= DateTime.UtcNow.AddMinutes(-1) &&
s.TimeStamp <= DateTime.UtcNow.AddMinutes(1))
.ToArray();
}
}
}
The problem is that T doesn't have a TimeStamp property as it's a generic type. If you always have to access the TimeStamp of whatever type you process in your collection, you could consider using an interface that has TimeStamp as a get function. All the types you want to process would have to implement that interface.
public interface MyInterface
{
TimeSpan TimeStamp { get; } //or whatever type your are using for your TimeStamp property
}
var collection = this.GetDatabaseConnection().GetCollection<MyInterface>
(collectionName);
var filter = Builders<MyInterface>.Filter.Where(result => result.TimeStamp >=
startTime && result.TimeStamp <= endTime);
List<MyInterface> queryData = collection.Find<MyInterface>(filter,null).ToList();
This way it's still quite generic. If you want to still use type T you would have to work with reflection to find the property TimeStamp on your processed type.
Edit: Some advice for using type T: You always have to consider that T can be anything, from an integer to any other object imaginable. Sometimes it can be quite useful if you have a method for example that doesn't need to access any properties on the type T object it is given but is used for many different types. I lately used T to build a little ParseOrDefault method to catch values that can't be converted:
private T ParseOrDefault<T>(Object value, T defaultValue)
{
try
{
return (T)Convert.ChangeType(value, typeof(T));
}
catch (Exception)
{
return defaultValue;
}
}
As soon as you have to deal with more specific use cases T is mostly not that useful.
after reading your comments on my first answer, i'd like to propose the following solution using MongoDB.Entities
hope this is more or less what you're trying to achieve...
using MongoDB.Entities;
using System;
using System.Collections.Generic;
namespace StackOverflow
{
public class Program
{
public class MySample : Entity
{
public DateTime TimeStamp { get; set; }
}
public class Sample1 : MySample
{
public string SomeProp { get; set; }
}
public class Sample2 : MySample
{
public string AnotherProp { get; set; }
}
private static void Main(string[] args)
{
new DB("test");
var sample1 = new Sample1 { SomeProp = "some prop value", TimeStamp = DateTime.UtcNow };
var sample2 = new Sample2 { AnotherProp = "another prop", TimeStamp = DateTime.UtcNow };
DB.Save(sample1);
DB.Save(sample2);
var s1 = FindSamples<Sample1>();
var s2 = FindSamples<Sample2>();
List<T> FindSamples<T>() where T : MySample
{
return DB.Find<T>()
.Many(s =>
s.TimeStamp >= DateTime.UtcNow.AddMinutes(-1) &&
s.TimeStamp <= DateTime.UtcNow.AddMinutes(1));
}
}
}
}
Is it possible to simplify this logic, Is there generic way to do it.
The code finds marked attributes and parses it according to the attribute type.
Please suggest some way to optimize this code, all the data type of Product class will be string, I'm getting product input as xml directly converting serialized data to a class with decimal,int,float will not give proper error message, If there is list of item it throws error in xml we wont know which row has caused the error.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace TestSolution
{
public interface ICustomParser
{
bool Parse(string input);
}
public class DecimalParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
decimal decimalValue;
return decimal.TryParse(input, out decimalValue);
}
}
public class intParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
int intValue;
return int.TryParse(input, out intValue);
}
}
public class Product
{
[DecimalParser]
public string Weight { get; set; }
[intParser]
public string NoOfItems { get; set; }
[intParser]
public string GRodes { get; set; }
[intParser]
public string WRodes { get; set; }
}
class Program
{
static void Main(string[] args)
{
var sb = Validate(new Product() { NoOfItems = "1", GRodes = "4", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
sb = Validate(new Product() { NoOfItems = "1", GRodes = "4w", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
Console.ReadKey();
}
private static string Validate(Product product)
{
var sb = new StringBuilder();
foreach (var property in product.GetType().GetProperties())
{
var value = Convert.ToString(property.GetValue(product, null));
var sel = property.GetAttribute<ICustomParser>();
if (sel == null) continue;
var parserinstance = (ICustomParser)Activator.CreateInstance(sel.GetType());
if (parserinstance.Parse(value)) continue;
sb.AppendLine(string.Format("{0} Has invalid value", property.Name));
}
return sb.ToString();
}
}
public static class Extensions
{
public static T GetAttribute<T>(this PropertyInfo property)
{
return (T)property.GetCustomAttributes(false).Where(s => s is T).FirstOrDefault();
}
}
}
If you only have one type (Product), it probably isn't worth it - just write the validation code explicitly without all the fancy stuff. If, however, you have multiple types to inspect (perhaps known only at runtime):
It really depends how fast it needs to be. How often does this run? If it is periodic, then there isn't a vast amount to do - the main change would be to just cast the parser directly:
var parserInstance = (ICustomParser)sel;
(it already is the attribute type)
If it is critical path, then there is a lot you can do to beef it up, but you get into the realm of metaprogramming - which is essentially what most tools like serializers and ORMs do to reduce runtime reflection. If you're not familiar with hacking IL at runtime, I would recommend looking at a tool like "Sigil" (available on nuget) that makes it hard to get wrong (or at least: tells you what you've done wrong). Essentially, you can inspect the data structure and then emit the IL that matches what it would look like if you were doing it all in explicit code; for example, emitting IL that looks kinda like:
static readonly DecimalParserAttribute _decimal = new DecimalParserAttribute();
public static void Validate(Product product) {
var sb = new StringBuilder();
if(!_decimal.Parse(product.Weight)) {
sb.Append(...);
}
// ... etc
...,
}
I am using Roslyn and I have the following class:
var source = #"
using System;
class MyClass : MyBaseClass {
static void Main(string[] args) {
Console.WriteLine(""Hello, World!"");
}
}";
// Parsing
SyntaxTree tree = CSharpSyntaxTree.ParseText(source);
// This uses an internal function (working)
// That gets the first node of type `SimpleBaseTypeSyntax`
SimpleBaseTypeSyntax simpleBaseType = GetNBaseClassNode(tree);
Getting the base class name
I successfully get access to node SimpleBaseTypeSyntax which contains what I need. In fact, if I use the syntax explorer, I get:
Node IdentifierToken has everything I need has its Text, Value and ValueText properties are "MyBaseClass"!
However, while in the syntax explorer I can see all these values, I cannot access them programmatically.
So I try retrieving the node programmatically:
IdentifierNameSyntax identifierNode =
simpleBaseType.ChildNodes().OfType<IdentifierNameSyntax>().First();
SyntaxToken identifier = simpleBaseType.Identifier;
string name = identifier.Text;
But name is empty string. Same as identifier.Value and identifier.ValueText.
What am I doing wrong? Maybe I am doing wrong, so how would you retrieve the base class name?
Another attempt: Using the semantic model
I started thinking that I need the semantic model for this type of information:
IdentifierNameSyntax identifierNode =
simpleBaseType .ChildNodes().OfType<IdentifierNameSyntax>().First();
SemanticModel semanticModel =
CSharpCompilation.Create("Class")
.AddReferences(MetadataReference.CreateFromFile(
typeof(object).Assembly.Location))
.AddSyntaxTrees(tree).GetSemanticModel(tree);
SymbolInfo symbolInfo = this.semanticModel.GetSymbolInfo(identifierNode);
string name = symbolInfo.Symbol.Name;
This throws exception as symbolInfo.Symbol is null.
I actually don't know why you can't pass the BaseTypeSyntax to the semantic model via GetSymbolInfo(), but it's also returning null for me with no errors.
Anyways, here's an approach that works:
var tree = CSharpSyntaxTree.ParseText(#"
using System;
class MyBaseClass
{
}
class MyClass : MyBaseClass {
static void Main(string[] args) {
Console.WriteLine(""Hello, World!"");
}
}");
var Mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var compilation = CSharpCompilation.Create("MyCompilation",
syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
var model = compilation.GetSemanticModel(tree);
var myClass = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().Last();
var myClassSymbol = model.GetDeclaredSymbol(myClass) as ITypeSymbol;
var baseTypeName = myClassSymbol.BaseType.Name;
You'll want to use the semantic model here because you won't be able to reliably tell if you're dealing with an interface or a base type at the syntax level.
I can see that you're trying to build an analyzer with the Roslyn API.
You do know that there are other ways to test your analyzer logic? Using unit test files instead of directly having the source inside the analyzer.
Using this idea, you entirely build your analyzer with the template provided by Visual Studio, where you must inherit from DiagnosticAnalyzer and you create your analysis code logic.
For your situation, you should look at ClassDeclaration and easily access the BaseTypes property inside the Node.
public bool SomeTriedDiagnosticMethod(SyntaxNodeAnalysisContext nodeContext)
{
var classDeclarationNode = nodeContext.Node as ClassDeclarationSyntax;
if (classDeclarationNode == null) return false;
var baseType = classDeclarationNode.BaseList.Types.FirstOrDefault(); // Better use this in all situations to be sure code won't break
var nameOfFirstBaseType = baseType.Type.ToString();
return nameOfFirstBaseType == "BaseType";
}
protected static bool IsWebPage(SyntaxNodeAnalysisContext context, ClassDeclarationSyntax classDeclaration)
{
INamedTypeSymbol iSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclaration) as INamedTypeSymbol;
INamedTypeSymbol symbolBaseType = iSymbol?.BaseType;
while (symbolBaseType != null)
{
if (symbolBaseType.ToString() == "System.Web.UI.Page")
return true;
symbolBaseType = symbolBaseType.BaseType;
}
return false;
}
This is my helper class that finds all properties, class name, class namespace and base classes.
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace MyProject
{
public class CsharpClass
{
public string Name { get; set; }
public string Namespace { get; set; }
public List<CsharpProperty> Properties { get; set; }
public List<string> BaseClasses { get; set; }
public class CsharpProperty
{
public string Name { get; set; }
public string Type { get; set; }
public CsharpProperty(string name, string type)
{
Name = name;
Type = type;
}
}
public CsharpClass()
{
Properties = new List<CsharpProperty>();
BaseClasses = new List<string>();
}
}
public static class CsharpClassParser
{
public static CsharpClass Parse(string content)
{
var csharpClass = new CsharpClass();
var tree = CSharpSyntaxTree.ParseText(content);
var members = tree.GetRoot().DescendantNodes().OfType<MemberDeclarationSyntax>();
foreach (var member in members)
{
if (member is PropertyDeclarationSyntax property)
{
csharpClass.Properties.Add(new CsharpClass.CsharpProperty(
property.Identifier.ValueText, property.Type.ToString()));
}
if (member is NamespaceDeclarationSyntax namespaceDeclaration)
{
csharpClass.Namespace = namespaceDeclaration.Name.ToString();
}
if (member is ClassDeclarationSyntax classDeclaration)
{
csharpClass.Name = classDeclaration.Identifier.ValueText;
csharpClass.BaseClasses = GetBaseClasses(classDeclaration).ToList();
}
//if (member is MethodDeclarationSyntax method)
//{
// Console.WriteLine("Method: " + method.Identifier.ValueText);
//}
}
return csharpClass;
}
private static IEnumerable<string> GetBaseClasses(ClassDeclarationSyntax classDeclaration)
{
if (classDeclaration == null)
{
return null;
}
if (classDeclaration.BaseList == null)
{
return null;
}
return classDeclaration.BaseList.Types.Select(x => x.Type.ToString());
}
}
}
Usage:
const string content = #"
namespace Acme.Airlines.AirCraft
{
public class AirCraft
{
public virtual string Name { get; set; }
public virtual int Code { get; set; }
public AirCraft()
{
}
}
}";
var csharpClass = CsharpClassParser.Parse(content);
Console.WriteLine(csharpClass.Name);
Console.WriteLine(csharpClass.Namespace);
Console.WriteLine(csharpClass.Properties.Count);
Console.WriteLine(csharpClass.BaseClasses.Count);
This is all in C#, using .NET 2.0.
I have two lists of objects. They are not related objects, but they do have certain things in common that can be compared, such as a GUID-based unique identifier. These two lists need to be filtered by another list which just contains GUIDs which may or may not match up with the IDs contained in the first two lists.
I have thought about the idea of casting each object list to just object and sorting by that, but I'm not sure that I'll be able to access the ID property once it's cast, and I'm thinking that the method to sort the two lists should be somewhat dumb in knowing what the list to be sorted is.
What would be the best way to bring in each object list so that it can be sorted against the list with only the IDs?
You should make each of your different objects implement a common interface. Then create an IComparer<T> for that interface and use it in your sort.
Okay, if you have access to modify your original classes only to add the interface there, Matthew had it spot on. I went a little crazy here and defined out a full solution using 2.0 anonymous delegates. (I think I'm way addicted to 3.0 Lambda; otherwise, I probably would've written this out in foreach loops if I was using 2005 still).
Basically, create an interface with the common properties. Make yoru two classes implement the interface. Create a common list casted as the interface, cast and rip the values into the new list; remove any unmatched items.
//Program Output:
List1:
206aa77c-8259-428b-a4a0-0e005d8b016c
64f71cc9-596d-4cb8-9eb3-35da3b96f583
List2:
10382452-a7fe-4307-ae4c-41580dc69146
97f3f3f6-6e64-4109-9737-cb72280bc112
64f71cc9-596d-4cb8-9eb3-35da3b96f583
Matches:
64f71cc9-596d-4cb8-9eb3-35da3b96f583
Press any key to continue . . .
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication8
{
class Program
{
static void Main(string[] args)
{
//test initialization
List<ClassTypeA> list1 = new List<ClassTypeA>();
List<ClassTypeB> list2 = new List<ClassTypeB>();
ClassTypeA citem = new ClassTypeA();
ClassTypeB citem2 = new ClassTypeB();
citem2.ID = citem.ID;
list1.Add(new ClassTypeA());
list1.Add(citem);
list2.Add(new ClassTypeB());
list2.Add(new ClassTypeB());
list2.Add(citem2);
//new common list.
List<ICommonTypeMakeUpYourOwnName> common_list =
new List<ICommonTypeMakeUpYourOwnName>();
//in english, give me everything in list 1
//and cast it to the interface
common_list.AddRange(
list1.ConvertAll<ICommonTypeMakeUpYourOwnName>(delegate(
ClassTypeA x) { return (ICommonTypeMakeUpYourOwnName)x; }));
//in english, give me all the items in the
//common list that don't exist in list2 and remove them.
common_list.RemoveAll(delegate(ICommonTypeMakeUpYourOwnName x)
{ return list2.Find(delegate(ClassTypeB y)
{return y.ID == x.ID;}) == null; });
//show list1
Console.WriteLine("List1:");
foreach (ClassTypeA item in list1)
{
Console.WriteLine(item.ID);
}
//show list2
Console.WriteLine("\nList2:");
foreach (ClassTypeB item in list2)
{
Console.WriteLine(item.ID);
}
//show the common items
Console.WriteLine("\nMatches:");
foreach (ICommonTypeMakeUpYourOwnName item in common_list)
{
Console.WriteLine(item.ID);
}
}
}
interface ICommonTypeMakeUpYourOwnName
{
Guid ID { get; set; }
}
class ClassTypeA : ICommonTypeMakeUpYourOwnName
{
Guid _ID;
public Guid ID {get { return _ID; } set { _ID = value;}}
int _Stuff1;
public int Stuff1 {get { return _Stuff1; } set { _Stuff1 = value;}}
string _Stuff2;
public string Stuff2 {get { return _Stuff2; } set { _Stuff2 = value;}}
public ClassTypeA()
{
this.ID = Guid.NewGuid();
}
}
class ClassTypeB : ICommonTypeMakeUpYourOwnName
{
Guid _ID;
public Guid ID {get { return _ID; } set { _ID = value;}}
int _Stuff3;
public int Stuff3 {get { return _Stuff3; } set { _Stuff3 = value;}}
string _Stuff4;
public string Stuff4 {get { return _Stuff4; } set { _Stuff4 = value;}}
public ClassTypeB()
{
this.ID = Guid.NewGuid();
}
}
}
Using only .NET 2.0 methods:
class Foo
{
public Guid Guid { get; }
}
List<Foo> GetFooSubset(List<Foo> foos, List<Guid> guids)
{
return foos.FindAll(foo => guids.Contains(foo.Guid));
}
If your classes don't implement a common interface, you'll have to implement GetFooSubset for each type individually.
I'm not sure that I fully understand what you want, but you can use linq to select out the matching items from the lists as well as sorting them. Here is a simple example where the values from one list are filtered on another and sorted.
List<int> itemList = new List<int>() { 9,6,3,4,5,2,7,8,1 };
List<int> filterList = new List<int>() { 2, 6, 9 };
IEnumerable<int> filtered = itemList.SelectMany(item => filterList.Where(filter => filter == item)).OrderBy(p => p);
I haven't had a chance to use AutoMapper yet, but from what you describe you wish to check it out. From Jimmy Bogard's post:
AutoMapper conventions
Since AutoMapper flattens, it will
look for:
Matching property names
Nested property names (Product.Name
maps to ProductName, by assuming a
PascalCase naming convention)
Methods starting with the word “Get”,
so GetTotal() maps to Total
Any existing type map already
configured
Basically, if you removed all the
“dots” and “Gets”, AutoMapper will
match property names. Right now,
AutoMapper does not fail on mismatched
types, but for some other reasons.
I am not totally sure what you want as your end results, however....
If you are comparing the properties on two different types you could project the property names and corresponding values into two dictionaries. And with that information do some sort of sorting/difference of the property values.
Guid newGuid = Guid.NewGuid();
var classA = new ClassA{Id = newGuid};
var classB = new ClassB{Id = newGuid};
PropertyInfo[] classAProperties = classA.GetType().GetProperties();
Dictionary<string, object> classAPropertyValue = classAProperties.ToDictionary(pName => pName.Name,
pValue =>
pValue.GetValue(classA, null));
PropertyInfo[] classBProperties = classB.GetType().GetProperties();
Dictionary<string, object> classBPropetyValue = classBProperties.ToDictionary(pName => pName.Name,
pValue =>
pValue.GetValue(classB, null));
internal class ClassB
{
public Guid Id { get; set; }
}
internal class ClassA
{
public Guid Id { get; set; }
}
classAPropertyValue
Count = 1
[0]: {[Id, d0093d33-a59b-4537-bde9-67db324cf7f6]}
classBPropetyValue
Count = 1
[0]: {[Id, d0093d33-a59b-4537-bde9-67db324cf7f6]}
Thist should essentially get you what you want - but you may be better of using linq
class T1
{
public T1(Guid g, string n) { Guid = g; MyName = n; }
public Guid Guid { get; set; }
public string MyName { get; set; }
}
class T2
{
public T2(Guid g, string n) { ID = g; Name = n; }
public Guid ID { get; set; }
public string Name { get; set; }
}
class Test
{
public void Run()
{
Guid G1 = Guid.NewGuid();
Guid G2 = Guid.NewGuid();
Guid G3 = Guid.NewGuid();
List<T1> t1s = new List<T1>() {
new T1(G1, "one"),
new T1(G2, "two"),
new T1(G3, "three")
};
List<Guid> filter = new List<Guid>() { G2, G3};
List<T1> filteredValues1 = t1s.FindAll(delegate(T1 item)
{
return filter.Contains(item.Guid);
});
List<T1> filteredValues2 = t1s.FindAll(o1 => filter.Contains(o1.Guid));
}
}
Is it possible to have an anonymous type implement an interface?
I've got a piece of code that I would like to work, but don't know how to do this.
I've had a couple of answers that either say no, or create a class that implements the interface construct new instances of that. This isn't really ideal, but I'm wondering if there is a mechanism to create a thin dynamic class on top of an interface which would make this simple.
public interface DummyInterface
{
string A { get; }
string B { get; }
}
public class DummySource
{
public string A { get; set; }
public string C { get; set; }
public string D { get; set; }
}
public class Test
{
public void WillThisWork()
{
var source = new DummySource[0];
var values = from value in source
select new
{
A = value.A,
B = value.C + "_" + value.D
};
DoSomethingWithDummyInterface(values);
}
public void DoSomethingWithDummyInterface(IEnumerable<DummyInterface> values)
{
foreach (var value in values)
{
Console.WriteLine("A = '{0}', B = '{1}'", value.A, value.B);
}
}
}
I've found an article Dynamic interface wrapping that describes one approach. Is this the best way of doing this?
No, anonymous types cannot implement an interface. From the C# programming guide:
Anonymous types are class types that consist of one or more public read-only properties. No other kinds of class members such as methods or events are allowed. An anonymous type cannot be cast to any interface or type except for object.
While the answers in the thread are all true enough, I cannot resist the urge to tell you that it in fact is possible to have an anonymous class implement an interface, even though it takes a bit of creative cheating to get there.
Back in 2008 I was writing a custom LINQ provider for my then employer, and at one point I needed to be able to tell "my" anonymous classes from other anonymous ones, which meant having them implement an interface that I could use to type check them. The way we solved it was by using aspects (we used PostSharp), to add the interface implementation directly in the IL. So, in fact, letting anonymous classes implement interfaces is doable, you just need to bend the rules slightly to get there.
Casting anonymous types to interfaces has been something I've wanted for a while but unfortunately the current implementation forces you to have an implementation of that interface.
The best solution around it is having some type of dynamic proxy that creates the implementation for you. Using the excellent LinFu project you can replace
select new
{
A = value.A,
B = value.C + "_" + value.D
};
with
select new DynamicObject(new
{
A = value.A,
B = value.C + "_" + value.D
}).CreateDuck<DummyInterface>();
Anonymous types can implement interfaces via a dynamic proxy.
I wrote an extension method on GitHub and a blog post http://wblo.gs/feE to support this scenario.
The method can be used like this:
class Program
{
static void Main(string[] args)
{
var developer = new { Name = "Jason Bowers" };
PrintDeveloperName(developer.DuckCast<IDeveloper>());
Console.ReadKey();
}
private static void PrintDeveloperName(IDeveloper developer)
{
Console.WriteLine(developer.Name);
}
}
public interface IDeveloper
{
string Name { get; }
}
No; an anonymous type can't be made to do anything except have a few properties. You will need to create your own type. I didn't read the linked article in depth, but it looks like it uses Reflection.Emit to create new types on the fly; but if you limit discussion to things within C# itself you can't do what you want.
The best solution is just not to use anonymous classes.
public class Test
{
class DummyInterfaceImplementor : IDummyInterface
{
public string A { get; set; }
public string B { get; set; }
}
public void WillThisWork()
{
var source = new DummySource[0];
var values = from value in source
select new DummyInterfaceImplementor()
{
A = value.A,
B = value.C + "_" + value.D
};
DoSomethingWithDummyInterface(values.Cast<IDummyInterface>());
}
public void DoSomethingWithDummyInterface(IEnumerable<IDummyInterface> values)
{
foreach (var value in values)
{
Console.WriteLine("A = '{0}', B = '{1}'", value.A, value.B);
}
}
}
Note that you need to cast the result of the query to the type of the interface. There might be a better way to do it, but I couldn't find it.
The answer to the question specifically asked is no. But have you been looking at mocking frameworks? I use MOQ but there's millions of them out there and they allow you to implement/stub (partially or fully) interfaces in-line. Eg.
public void ThisWillWork()
{
var source = new DummySource[0];
var mock = new Mock<DummyInterface>();
mock.SetupProperty(m => m.A, source.Select(s => s.A));
mock.SetupProperty(m => m.B, source.Select(s => s.C + "_" + s.D));
DoSomethingWithDummyInterface(mock.Object);
}
Another option is to create a single, concrete implementing class that takes lambdas in the constructor.
public interface DummyInterface
{
string A { get; }
string B { get; }
}
// "Generic" implementing class
public class Dummy : DummyInterface
{
private readonly Func<string> _getA;
private readonly Func<string> _getB;
public Dummy(Func<string> getA, Func<string> getB)
{
_getA = getA;
_getB = getB;
}
public string A => _getA();
public string B => _getB();
}
public class DummySource
{
public string A { get; set; }
public string C { get; set; }
public string D { get; set; }
}
public class Test
{
public void WillThisWork()
{
var source = new DummySource[0];
var values = from value in source
select new Dummy // Syntax changes slightly
(
getA: () => value.A,
getB: () => value.C + "_" + value.D
);
DoSomethingWithDummyInterface(values);
}
public void DoSomethingWithDummyInterface(IEnumerable<DummyInterface> values)
{
foreach (var value in values)
{
Console.WriteLine("A = '{0}', B = '{1}'", value.A, value.B);
}
}
}
If all you are ever going to do is convert DummySource to DummyInterface, then it would be simpler to just have one class that takes a DummySource in the constructor and implements the interface.
But, if you need to convert many types to DummyInterface, this is much less boiler plate.
Using Roslyn, you can dynamically create a class which inherits from an interface (or abstract class).
I use the following to create concrete classes from abstract classes.
In this example, AAnimal is an abstract class.
var personClass = typeof(AAnimal).CreateSubclass("Person");
Then you can instantiate some objects:
var person1 = Activator.CreateInstance(personClass);
var person2 = Activator.CreateInstance(personClass);
Without a doubt this won't work for every case, but it should be enough to get you started:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Publisher
{
public static class Extensions
{
public static Type CreateSubclass(this Type baseType, string newClassName, string newNamespace = "Magic")
{
//todo: handle ref, out etc.
var concreteMethods = baseType
.GetMethods()
.Where(method => method.IsAbstract)
.Select(method =>
{
var parameters = method
.GetParameters()
.Select(param => $"{param.ParameterType.FullName} {param.Name}")
.ToString(", ");
var returnTypeStr = method.ReturnParameter.ParameterType.Name;
if (returnTypeStr.Equals("Void")) returnTypeStr = "void";
var methodString = #$"
public override {returnTypeStr} {method.Name}({parameters})
{{
Console.WriteLine(""{newNamespace}.{newClassName}.{method.Name}() was called"");
}}";
return methodString.Trim();
})
.ToList();
var concreteMethodsString = concreteMethods
.ToString(Environment.NewLine + Environment.NewLine);
var classCode = #$"
using System;
namespace {newNamespace}
{{
public class {newClassName}: {baseType.FullName}
{{
public {newClassName}()
{{
}}
{concreteMethodsString}
}}
}}
".Trim();
classCode = FormatUsingRoslyn(classCode);
/*
var assemblies = new[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(baseType.Assembly.Location),
};
*/
var assemblies = AppDomain
.CurrentDomain
.GetAssemblies()
.Where(a => !string.IsNullOrEmpty(a.Location))
.Select(a => MetadataReference.CreateFromFile(a.Location))
.ToArray();
var syntaxTree = CSharpSyntaxTree.ParseText(classCode);
var compilation = CSharpCompilation
.Create(newNamespace)
.AddSyntaxTrees(syntaxTree)
.AddReferences(assemblies)
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
var result = compilation.Emit(ms);
//compilation.Emit($"C:\\Temp\\{newNamespace}.dll");
if (result.Success)
{
ms.Seek(0, SeekOrigin.Begin);
Assembly assembly = Assembly.Load(ms.ToArray());
var newTypeFullName = $"{newNamespace}.{newClassName}";
var type = assembly.GetType(newTypeFullName);
return type;
}
else
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (Diagnostic diagnostic in failures)
{
Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
return null;
}
}
}
public static string ToString(this IEnumerable<string> list, string separator)
{
string result = string.Join(separator, list);
return result;
}
public static string FormatUsingRoslyn(string csCode)
{
var tree = CSharpSyntaxTree.ParseText(csCode);
var root = tree.GetRoot().NormalizeWhitespace();
var result = root.ToFullString();
return result;
}
}
}