Here's the code that I'm attempting to do:
public IList<IOperator> GetAll()
{
using (var c = new MyDataContext())
{
return c.Operators.ToList();
}
}
Operator implements IOperator, but I'm getting the following compilation error:
Cannot implicitly convert type 'System.Collections.Generic.List<MyProject.Core.Operator>' to 'System.Collections.Generic.IList<MyProject.Core.Model.IOperator>'. An explicit conversion exists (are you missing a cast?)
How do I cast this to get what I need?
Try the Cast<>() method:
return c.Operators.Cast<IOperator>().ToList();
If I change the code to the following:
public IList<IOperator> GetAll()
{
using (var c = new MyDataContext())
{
var operators = (from o in c.Operators
select o).Cast<IOperator>();
return operators.ToList();
}
}
it not only compiles but actually works! Thanks for the nudges in the right direction.
Edit: Actually,
return (List< IOperator >)c.Operators.ToList();
would not do the trick. Sorry
Use ConvertAll<>
http://msdn.microsoft.com/en-us/library/kt456a2y.aspx
e.g.: In this case, TEntity must be an IBusinessUnit, but is a class, so i have the same trouble of converting List<Operator> to List<IOperator> (assuming Operator implements IOperator).
In your case, like you said, Operator doesn't impelement IOperator, but that doesn't matter - this will still work -
public static IList<IBusinessUnit> toIBusinessUnitIList(List<TEntity> items)
{
return items.ConvertAll<IBusinessUnit>(new Converter<TEntity, IBusinessUnit>(TEntityToIBuisinessUnit));
}
/// <summary>
/// Callback for List<>.ConvertAll() used above.
/// </summary>
/// <param name="md"></param>
/// <returns></returns>
private static IBusinessUnit TEntityToIBuisinessUnit(TEntity te)
{
return te; // In your case, do whatever magic you need to do to convert an Operator to an IOperator here.
}
Related
My problem is very simple, but all the options confuse me...
In my MEF/Prism-application, I want to attach a specific behavior to one specific region. The doumentation says, that you can do it that way:
IRegion region = regionManager.Region["Region1"];
region.Behaviors.Add("MyBehavior", new MyRegion());
But where should I put this? Is there some place, this is supposed to be done in a bootstrapper method? Currently, I am adding the behavior like this in the Loaded-event of the shell:
/// <summary>
/// Interaction logic for Shell.xaml
/// </summary>
[Export(typeof(Shell))]
public partial class Shell
{
[ImportingConstructor]
public Shell(IRegionManager regionManager, ElementViewInjectionBehavior elementViewInjectionBehavior)
{
InitializeComponent();
Loaded += (sender, args) =>
{
IRegion region = regionManager.Regions[RegionNames.ElementViewRegion];
region.Behaviors.Add("ElementViewInjection", elementViewInjectionBehavior);
};
}
}
Is this a good solution. I'd rather do it in the bootstrapper, so that it is done in the same place as the other region behavior registrations (ConfigureDefaultRegionBehaviors()).
So, the question: Where is the best place to add the behavior to one single region?
I just came up with a slightly improved solution, using a static string collection in the behavior to add the regions to attach the behavior to.
public class ViewModelInjectionBehavior : RegionBehavior, IDisposable
{
private static List<string> _regionNames;
public static List<string> Regions
{
get { return _regionNames ?? (_regionNames = new List<string>()); }
}
protected override void OnAttach()
{
if (Regions.Contains(Region.Name)) {...}
}
}
Then in my bootstrapper, I can define the regions:
protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
{
var behaviorFactory = base.ConfigureDefaultRegionBehaviors();
ViewModelInjectionBehavior.Regions.Add(RegionNames.ElementViewRegion);
behaviorFactory.AddIfMissing("ElementViewInjectionBehavior", typeof(ViewModelInjectionBehavior));
return behaviorFactory;
}
At least, the behavior is universally usable now...
We had the same issue - in the end we just checked the region name in the region behaviour and acted only if it was that region that we wanted, kind of sucks because you are attaching the behaviour to all regions - but for us it was better than the suggested solution..
An example looks like :
public class TrackViewOpenerBehaviour : IRegionBehavior
{
public IRegion Region { get; set; }
public void Attach()
{
if (this.Region.Name == ApplicationRegions.WorkspaceRegion
|| this.Region.Name == ApplicationRegions.DialogRegion)
{
this.Region.Views.CollectionChanged += (sender, e) =>
{
//Code Here.
};
}
}
}
I always thought maybe we could create a behaviour that was responsible for attaching other behaviours to specfiic regions for us, then we could register that in the bootstrapper - but never got round to it.
This problem occurs in both NHibernate 2 and 3. I have a Class A that has a member set of class B. Querying the classes directly executes nicely. But when I pass one of the expressions involving class B into a method I get the following error:
System.ArgumentException: Object of type 'System.Linq.Expressions.ConstantExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.
As far as I can see I am passing the exact same expression into the Any() method. But for some reason they are treated differently. I have done some debugging and it looks like in the first method, the expression is treated as an expression with NodeType 'Quote', while the same expression in the 2nd method seems to be treated as an expression with NodeType 'Constant'. The parent expression of the expression in the 2nd method has a NodeType 'MemberAccess'. So it looks like the expression tree is different in the different test methods. I just don't understand why and what to do to fix this.
Classes involvend:
public class A
{
public virtual int Id { get; set; }
public virtual ISet<B> DataFields { get; set; }
}
public class B
{
public virtual int Id { get; set; }
}
Sample test code:
[TestMethod]
public void TestMethod1()
{
using (ISession session = sessionFactory.OpenSession())
{
var records = session.Query<A>()
.Where<A>(a => a.DataFields
.Any(b => b.Id == 1));
Console.Write("Number of records is {0}", records.Count());
}
}
[TestMethod]
public void TestMethod2()
{
GetAsWhereB(b => b.Id == 1);
}
private void GetAsWhereB(Func<B, bool> where)
{
using (ISession session = sessionFactory.OpenSession())
{
var records = session.Query<A>()
.Where(a => a.DataFields
.Any(where));
Console.Write("Number of records is {0}", records.Count());
}
}
This is one problem:
private void GetAsWhereB(Func<B, bool> where)
That's taking a delegate - you want an expression tree otherwise NHibernate can't get involved. Try this:
private void GetAsWhereB(Expression<Func<B, bool>> where)
As an aside, your query is hard to read because of your use of whitespace. I would suggest that instead of:
var records = session.Query<A>().Where<A>(a => a.DataFields.
Any(b => b.Id == 1));
you make it clear that the "Any" call is on DataFields:
var records = session.Query<A>().Where<A>(a => a.DataFields
.Any(b => b.Id == 1));
I'd also suggest that you change the parameter name from "where" to something like "whereExpression" or "predicate". Some sort of noun, anyway :)
Not quite sure if this is the proper solution or not. The problem feels like a bug and my solution like a workaround. Nonetheless the following works for me, which boils down to creating a 'copy' of the given expression by using its body and parameter to construct a new expression.
private void GetAsWhereB(Func<B, bool> where)
{
Expression<Func<T, bool>> w = Expression.Lambda<Func<T, bool>>(where.Body, where.Parameters);
using (ISession session = sessionFactory.OpenSession())
{
var records = session.Query<A>()
.Where(a => a.DataFields
.Any(w));
Console.Write("Number of records is {0}", records.Count());
}
}
I've got a class A that calls a method on interface B, passing to it one of its own methods as sort of a continuation that B is supposed to call when it has a result. The code seems to work fine in practice, but I can't figure out how to test it with Moq -- when I try the obvious thing, it produces System.ArgumentException : method argument length mismatch. Thought at first it might be my code, but it fails the same way with the following toy case:
public class A
{
readonly B myB;
public A (B b)
{
myB = b;
}
public void HandleC (C c)
{
// do something
}
public void DoFindC ()
{
myB.FindC (HandleC);
}
}
public interface B
{
// Finds a C and then passes it to handleC
void FindC (Action<C> handleC);
}
public interface C
{
}
[TestFixture()]
public class ATest
{
[Test()]
public void TestDoFindC ()
{
Mock<B> bMock = new Mock<B> ();
A a = new A(bMock.Object);
a.DoFindC();
bMock.Verify(b => b.FindC(a.HandleC));
}
}
I'm guessing there's some behind-the-scenes magic with delegates that I don't understand yet, being relatively new to C#, but what's the right way to test this?
Update: For reference, I'm using Mono 2.6.7 on MacOS 10.6.5 and targeting .NET 3.5.
Updated again: Best guess is that this is a Mono bug; I've filed it as https://bugzilla.novell.com/show_bug.cgi?id=656918.
Mono bug: https://bugzilla.novell.com/show_bug.cgi?id=656918.
Embarrassing question really -- I have Subsonic collection, then I filter out some data using Where.
MyColl.Where(it => it.foo()==true)
now I would like to pass those data still as Subsonic collection. How to do it (the most properly way)? I checked constructor for Subsonic collection, ToX() methods, and googled.
edit: Subsonic 2.x series.
Thank you in advance, and sorry for naive question.
In SubSonic 2.x, the data isn't actually filtered out with Where() until the query is re-executed against the database. I'm assuming that's the same in 3.0. In 2.x there was a .Filter() method that would do what you are looking for.
The .Filter() method gets added to the generated classes. Here's what mine looks like (it's customized from the default):
/// <summary>
/// Filters an existing collection based on the set criteria. This is an in-memory filter.
/// All existing wheres are retained.
/// </summary>
/// <returns>TblSomethingOrOtherCollection</returns>
public TblSomethingOrOtherCollection Filter(SubSonic.Where w)
{
return Filter(w, false);
}
/// <summary>
/// Filters an existing collection based on the set criteria. This is an in-memory filter.
/// Existing wheres can be cleared if not needed.
/// </summary>
/// <returns>TblSomethingOrOtherCollection</returns>
public TblSomethingOrOtherCollection Filter(SubSonic.Where w, bool clearWheres)
{
if (clearWheres)
{
this.wheres.Clear();
}
this.wheres.Add(w);
return Filter();
}
/// <summary>
/// Filters an existing collection based on the set criteria. This is an in-memory filter.
/// Thanks to developingchris for this!
/// </summary>
/// <returns>TblSomethingOrOtherCollection</returns>
public TblSomethingOrOtherCollection Filter()
{
for (int i = this.Count - 1; i > -1; i--)
{
TblSomethingOrOther o = this[i];
foreach (SubSonic.Where w in this.wheres)
{
bool remove = false;
System.Reflection.PropertyInfo pi = o.GetType().GetProperty(w.ColumnName);
if (pi != null && pi.CanRead)
{
object val = pi.GetValue(o, null);
if (w.ParameterValue is Array)
{
Array paramValues = (Array)w.ParameterValue;
foreach (object arrayVal in paramValues)
{
remove = !Utility.IsMatch(w.Comparison, val, arrayVal);
if (remove)
break;
}
}
else
{
remove = !Utility.IsMatch(w.Comparison, val, w.ParameterValue);
}
}
if (remove)
{
this.Remove(o);
break;
}
}
}
return this;
}
}
For some reason i could never get the inline method of filter to work, but its easy to use like this:
SubSonic.Where w = new Where();
w.ColumnName = Product.CatIDColumn.PropertyName;
w.Comparison = Comparison.Equals;
w.ParameterValue = "1";
ProductCollection objFilteredCol = objProdCollection.Where(w).Filter();
In this code from Microsoft's MVC Tutorial NerdDinners:
public class DinnerRepository {
private NerdDinnerDataContext db = new NerdDinnerDataContext();
//
// Query Methods
public IQueryable<Dinner> FindAllDinners() {
return db.Dinners;
}
public IQueryable<Dinner> FindUpcomingDinners() {
return from dinner in db.Dinners
where dinner.EventDate > DateTime.Now
orderby dinner.EventDate
select dinner;
}
public Dinner GetDinner(int id) {
return db.Dinners.SingleOrDefault(d => d.DinnerID == id);
}
//
// Insert/Delete Methods
public void Add(Dinner dinner) {
db.Dinners.InsertOnSubmit(dinner);
}
public void Delete(Dinner dinner) {
db.RSVPs.DeleteAllOnSubmit(dinner.RSVPs);
db.Dinners.DeleteOnSubmit(dinner);
}
//
// Persistence
public void Save() {
db.SubmitChanges();
}
}
What does:
public Dinner GetDinner(int id) {
return db.Dinners.SingleOrDefault(d => d.DinnerID == id);
}
the "d" mean? How does this code work? I know it it bringing back dinners where dinnerid matches id from the function parameter. I don't understand the "d goes to..." means. I know it is a lambda but I don't really get it. What is the "d" for? What does it do?
Could this have been written without the lambda here (how)?
You should probably read up on anonymous methods.
Basically the code you are referring to can be written as an anonymous method without lamba syntax like this:
public Dinner GetDinner(int id) {
return db.Dinners.SingleOrDefault(delegate (Dinner d) {
return d.DinnerID == id;
});
}
This is similar too...
from d in db.Dinners
where d.DinnerID == id
select d
The code basically loops around the dinners returning the first Dinner or the default if none is found.
This is a case where the naming conventions used in a sample aren't always appropriate in production. Using a "d" as a local variable is usually fround upon and choosing a variable name of "dinner" would probably be more appropriate, although in this case the scope of d is so small it is clear either way, as long as you know how lambda expressions work.
You need to understand lambda syntax and what it's used for.
Here's an article that does a decent job of explaining it.
However, to shortly answer your question in regards to the NerdDinner context, "d" in this context is just a parameter passed into the lamda expression that is a Dinner object.
This bit of code:
d => d.DinnerID == id
Can be thought of as defining a function of type Func<Dinner, bool>.
Whatever you pass it to, this function can be called, and passed Dinner, and it will give back a bool.
void Foo(Func<Dinner, bool> f)
{
bool result = f(new Dinner());
}
In your real example, the function SingleOrDefault will call the function you give it multiple times, passing it a different Dinner each time, and will return the Dinner for which the function returns true.
In fact, as you're using IQueryable, this is only conceptually what happens. The chances are, the code of the function is converted into SQL, and all the execution is done inside the database.