How to consume a method exported with MEF programatically? - mef

I'm exporting a method using MEF with the attribute [Export] and I need to consume this method using the Container (obtaining the method using GetExports).
GetExports returns an ExportedDelegate object that I have no idea how to extract the MethodInfo from.
Inspecting with the debugger I see it as a private property and I'm tempted to extract it using reflection but it doesn't feel like the right way of doing this.
Any ideas?
This problem is different than this one. I'm not trying to use [Import], I have to obtain and consume the method from the Container.

Alright guys so that was a tricky one but I'm leaving here as a reference.
All you have to do is to cast the value returned from MEF to a ExportedDelegate and call CreateDelegate the right way:
This sets the Import we want:
var importDefinition = new ImportDefinition(e => true, obj.GetType().FullName, ImportCardinality.ZeroOrMore, false, false);
var objectsWithMethods = container.GetExports(importDefinition)
.Where(x => x.Value is IYourInterface)
.Select(x => x.Value)
.ToList();
This gets the methods of the objects found above (iterate objectsWithMethods in a foreach using objectsWithMethod):
var endPointsImportDefinition = new ImportDefinition(e => true, objectsWithMethod.GetType().FullName, ImportCardinality.ZeroOrMore, false, false);
var endPoints = container.GetExports(endPointsImportDefinition)
.Where(x => x.Value is ExportedDelegate)
.Select(x => x.Value)
.ToList();
And finally to get MethodInfo (which allows you to run the method) you use:
var endPointMethod = (endPoint as ExportedDelegate).CreateDelegate(typeof(Delegate)).GetMethodInfo();
What also could be:
var endPointMethod = (endPoint as ExportedDelegate).CreateDelegate(typeof(Delegate)).Method;
Hope it helps anyone!

Related

How to perform subtraction between DateTime in a Linq to Sql Select() method

I've a linq query :
var NextWeekDate = DateTime.Now.AddDays(7);
var BirthData = db.EmployeeMasterAs
.Where(x => x.Emp_BirthDate >= CurrentDate)
.Select(x => new { x.Emp_BirthDate,
DaysRemaining = (NextWeekDate - x.Emp_BirthDate).Value.TotalDays
})
.OrderBy(x => x.Emp_BirthDate)
.ToList();
Note the element in Select() method, DaysRemaining = (NextWeekDate - x.Emp_BirthDate).Value.TotalDays, I want to get the difference between dates in days and save that to DaysRemaining, this query is not working and the exception that it throws :
DbArithmeticExpression arguments must have a numeric common type.
I don't know exactly how to achieve this, Any Ideas?
I think that LinqToSql does not support DateTime.Subtract. But you can use the preexisting function SqlMethods.DateDiffDay (https://msdn.microsoft.com/en-us/library/bb468730(v=vs.110).aspx)
Edit: SqlMethods is only intended for SQL Server. DbFunctions is the helper class to pick regardless of the database type.
Yep, Got it, So here is how it goes :
Performing arithmetic operations with Dates and Times is not supported in EF. EntityFramework cannot convert your code to SQL. Instead of that you can use DbFunctions.DiffDays( startExpression, endExpression) method:
db.EmployeeMasterAs
.Where(x => x.Emp_BirthDate >= CurrentDate)
.Select(x => new { x.Emp_BirthDate,
DaysRemaining = DbFunctions.DiffDays(x.Emp_BirthDate,NextWeek)
})
.OrderBy(x => x.Emp_BirthDate)
.ToList();
Furthermore : DbFunctions Functions methods are called canonical functions. And these are a set of functions, which are supported by all Entity Framework providers. These canonical functions will be translated to the corresponding data source functionality for the provider. Canonical functions are the preferred way to access functionality outside the core language, because they keep the queries portable.

Contains method not working mongodb c# driver linq [duplicate]

I'm using the Mongo LINQ Driver for C#, works great.
Sorting a lot of properties but heres a problem I can't solve, its probably simple.
var identifierList = new []{"10", "20", "30"};
var newList = list.Where(x => identifierList.Contains(x.Identifier));
This is NOT supported ...
So I could do something like:
var newList = list.Where(x => x.Identifier == "10" || x.Identifier == "20" || x.Identifier == "30");
But since the list is variable ... how do I construct the above? Or are there even better alternatives?
The list is of type IQueryable<MyCustomClass>
For information ... this is used as a filter of alot of properties. In SQL I could have a parent -> child relationship. But as I can't as the parent for the main ID I need to take all the ID's out and then construct it like this.
Hopes this makes sense. If needed I will explain more.
To answer my own question ... The Mongo Sharp LINQ driver has an extension method called "In" which does exactly what I need.
They have however implemented it in 1.5 so we can use the old way like: https://jira.mongodb.org/browse/CSHARP-462
var list = new []{"10", "10"};
search.Where(x => list.Contains(x.Id));
But the version 1.5 package is not on nuget yet.
However, this should work with the "In" extension that comes as a special surprise with the mongo-csharp-driver.
search.Where(x => x.In(list));
var identifierList = new []{"10", "20", "30"};
var newList = list.ToList().Where(x => identifierList.Contains(x.Identifier));
You will just have to use List instead of Ienumerable (do that by using the .ToList())
If it doesn't work please add your list TYPE

EF6 error when using in-memory testing

Mocked setup below (the GenerateTrades() and other methods in ContextFactory are just returning a List AsQueryable with sample data):
_trades = ContextFactory.GenerateTrades();
_hedges = ContextFactory.GenerateHedges();
_exposures = ContextFactory.GenerateExposures();
_ctx = new Mock<FxContext>();
var fakeTrades = new Mock<DbSet<Trade>>();
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.Provider).Returns(_trades.Provider);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.Expression).Returns(_trades.Expression);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.ElementType).Returns(_trades.ElementType);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.GetEnumerator()).Returns(_trades.GetEnumerator());
var fakeHedges = new Mock<DbSet<Hedge>>();
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.Provider).Returns(_hedges.Provider);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.Expression).Returns(_hedges.Expression);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.ElementType).Returns(_hedges.ElementType);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.GetEnumerator()).Returns(_hedges.GetEnumerator());
var fakeExposures = new Mock<DbSet<Exposure>>();
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.Provider).Returns(_exposures.Provider);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.Expression).Returns(_exposures.Expression);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.ElementType).Returns(_exposures.ElementType);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.GetEnumerator()).Returns(_exposures.GetEnumerator());
_ctx.Setup(c => c.Trades).Returns(fakeTrades.Object);
_ctx.Setup(c => c.Hedges).Returns(fakeHedges.Object);
_ctx.Setup(c => c.Exposures).Returns(fakeExposures.Object);
Part of test code looks like:
_sut = (from x in _ctx.Object.Hedges
where x.Id == ContextFactory.s_hedge01Id
select x).FirstOrDefault();
_ctx.Object.Hedges.Attach(_sut);
_ctx.Object.Entry(_sut).Collection(x => x.HedgedTrades).Load();
On the last line I get an exception:
{"Member 'Load' cannot be called for property 'HedgedTrades' because the entity of type 'Hedge' does not exist in the context. To add an entity to the context call the Add or Attach method of DbSet<Hedge>."}
I have verified that in fact the _sut Hedge is actually an instance of a Hedge (not null or a stub) and as the code seems to indicate, I have attached the Hedge to the context explicitly (though I would think the query should bring the object into the context automagically). Am I missing something?
It seems like here in your test you are mixing two separate approaches. Error you received states that you are trying to access DbContext inherited logic, but it is mocked. If you want to perform your unit tests against database with use of FxContext then do not mock it. If you want test other part of software then you should mock interface that FxContext should implement. This will enable you to fullfil dependency injection principle in your code which will help you then organize your test in more predictable way.

How to observe a collection of items for when they are all valid?

I'm using ReactiveUI and the provided ReactiveCollection<> class.
In a ViewModel I have a collection of objects, and I wish to create an observable that watches those items for their IsValid property.
This is the scenario I'm trying to solve. In my ViewModel's constructor.
this.Items = new ReactiveCollection<object>();
IObservable<bool> someObservable = // ... how do I watch Items so when
// any items IsValid property changes,
// this observable changes. There
// is an IValidItem interface.
this.TheCommand = new ReactiveCommand(someObservable);
...
interface IValidItem { bool IsValid { get; } }
EDIT Ana's answer got me most of the way there. The solution is the following.
this.Items = new ReactiveCollection<object>();
this.Items.ChangeTrackingEnabled = true;
var someObservable = this.Items.Changed
.Select(_ => this.Items.All(i => i.IsValid));
It depends on what you want to do with the results of IsValid. Here's how I would do it, though it's not entirely intuitive:
// Create a derived collection which are all the IsValid properties. We don't
// really care which ones are valid, rather that they're *all* valid
var isValidList = allOfTheItems.CreateDerivedCollection(x => x.IsValid);
// Whenever the collection changes in any way, check the array to see if all of
// the items are valid. We could probably do this more efficiently but it gets
// Tricky™
IObservable<bool> areAllItemsValid = isValidList.Changed.Select(_ => isValidList.All());
theCommand = new ReactiveCommand(areAllItemsValid);
Since you are using ReactiveUI, you have a few options. If your objects are ReactiveValidatedObjects you can actually use the ValidationObservable:
var someObservable = this.Items
.Select(o => o.ValidationObservable
.Select(chg => chg.GetValue()) //grab just the current bool from the change
.StartsWith(o.IsValid)) //prime all observables with current value
.CombineLatest(values => values.All());
If they aren't ReactiveValidatedObjects, but implement INotifyPropertyChanged, you would just replace the first line and use the handy ObservableForProperty extension method in ReactiveUI for those objects. Instead of o.ValidationObservable you would use o.ObservableForProperty(x => x.IsValid). The rest should be the same.
This is a pretty common use case and I've wrapped it in an extension method for IEnumerable<ReactiveValidatedObject>
I'm sure Paul Betts will come along with something more elegant, but this is what I do.

LINQ to Entities Contains Query

I'm trying to use Contains() in a simple query but it is failing, with the error :
Unable to create a constant value of type 'NewsletterApp.Models.NewsletterUser'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
Edit The intellisense actually directs me to use the NewsletterUser in Contains() -'(NewsletterUser item)'
I read that there were issues searching for an object using Contains() using EF with .NET 3.5, but I am using EF4.2 (also tried 4.1) with .NET 4.0 .
Code is below:
var db = new MyContext();
var newsletterUser = db.NewsletterUsers.Find(UserID);
var subscriberList = db.Subscribers
.Where(x => x.NewsletterList.ListOwner.NewsletterUsers.Contains(newsletterUser))
.ToList();
I suspect you want this
var db = new MyContext();
var newsletterUser = db.NewsletterUsers.Find(UserID);
var subscriberList = db.Subscribers
.Where(x => x.NewsletterList.ListOwner.NewsletterUsers
.Any(y => y.UserId == newsletterUser.UserId))
.ToList();
Any() checks for the existence of a item that fulfils the criteria specified in the lambda: "y => y.UserId == newsletterUser.UserId".
The exception you were getting: "Only primitive types ('such as Int32, String, and Guid') are supported in this context" is due to limitations set by LINQ to Entities. LINQ to Entities needs to resolve your query in a way that it can express to the database, and it can't do that with the Contains() method with anything other than a primitive type.
The thing is, the code you posted does run fine if you run it against an in memory collection (LINQ to Objects) - that's why it isn't flagged by the compiler.
Your query is wrong. Instead of comparing a property or field, you are comparing the whole object or entity, which can't be done in this manner.
Try the following code and it will work
var db = new MyContext();
var newsletterUser = db.NewsletterUsers.Find(UserID);
var subscriberList = db.Subscribers
.Where(x => x.NewsletterList.ListOwner.NewsletterUsers.UserId.Contains(newsletterUser.UserID))
.ToList();