I have a method that is exposed using interface in the business logic layer. It is as follows:
public interface IMyWorkingClass
{
IEnumerable<dynamic> GetSomeList();
}
public class MyWorkingClass : IMyWorkingClass
{
public IEnumerable<dynamic> GetSomeList()
{
dynamic foos = new List<dynamic>();
dynamic item = new ExpandoObject();
item.PropOne = (new Foo()).FooPropertyOne;
item.PropTwo = (new Bar()).BarPropertyOne;
foos.Add(item);
return foos;
}
}
public class Foo
{
public int FooId{get;set;}
public string FooPropertyOne{get;set;}
public string FooPropertyTwo{get;set;}
}
public class Bar
{
public int BarId{get;set;}
public string BarPropertyOne{get;set;}
public string BarPropertyTwo{get;set;}
}
There are a lot of different opinions/preferences out there about dynamic itself. I find them useful. One of my friends said dynamics are good but the way they are used above are not. The argument presented was that the compiler wont catch the things changed on dynamic object. I think the unit tests will be able to catch those. So I disagreed. What is your expert opinion? Thanks in advance 🙂
Update
Here’s bit clearer (hopefully) code:
public interface IMyWorkingClass
{
IEnumerable<dynamic> GetListOfClassesForStudentDynamicReturn();
IEnumerable<StudentClassInfo> GetListOfClassesForStudentStaticReturn();
}
public class MyWorkingClass : IMyWorkingClass
{
public IEnumerable<dynamic> GetListOfClassesForStudentDynamicReturn(Student student)
{
dynamic listOfClasses = new List<dynamic>();
// repository pattern is used in DAL
var datafromDB = (StudentCollegeClassRepo.GetQueryable(x=>x.StudentId==student.StudentId)
.select(item => new {
item.CollegeClassId
,item.CollegeClass.CollegeClassName
,item.IsEnabledForStudent
}).ToList();
foreach (var item in datafromDB)
{
dynamic classWithStudent = new ExpandoObject();
classWithStudent.CollegeClassId = item.CollegeClassId;
classWithStudent.CollegeClassName = item.CollegeClassName;
classWithStudent.IsEnabledForStudent = item.IsEnabledForStudent;
listOfClasses.Add(studentWithClass);
}
return listOfClasses;
}
public IEnumerable<StudentClassInfo> GetListOfClassesForStudentStaticReturn(Student student)
{
// repository pattern is used in DAL
var datafromDB = (StudentCollegeClassRepo.GetQueryable(x=>x.StudentId==student.StudentId)
.select(item => new StudentClassInfo {
CollegeClassId = item.CollegeClassId
,CollegeClassName = item.CollegeClass.CollegeClassName
,IsEnabledForStudent = item.IsEnabledForStudent
}).ToList();
return datafromDB;
}
}
// this class is like a viewmodel
public class StudentClassInfo
{
public int CollegeClassId { get; set; }
public string CollegeClassName { get; set; }
public bool IsEnabledForStudent { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string StudentName { get; set; }
}
public class StudentCollegeClass
{
public int StudentId { get; set; }
public int CollegeClassId { get; set; }
public bool IsEnabledForStudent { get; set; }
}
public class CollegeClass
{
public int CollegeClassId { get; set; }
public string CollegeClassName { get; set; }
}
Hopefully I made things little clearer now. So,method with dynamic return is ok or create a static type and have that returned instead? I am also learning how to ask question properly here.. Thanks for your patience and awesome replies 🙂
Despite what Skeet says 🙂 I’ll add some thoughts here.
If you start down the path of using Dynamics, you must shift your thinking. You don’t know what your object is, you only care about what it can do.
You find yourself not needing interfaces rather quickly – and then you ask yourself “WTF am I doing anyway?”. Which is always a great question to ask.
And then a shift happens as you start writing more tests to cover up the loss of a compiler check – you start writing methods a bit more clearly. You start relying on Factories and other classes to impose logic on top of these little bits of amorphous dynamic goo.
It’s incredibly freeing if you consider the mental shift. For instance you have a “MyWorkingClass” that does something on top of Foo/Bar. If that was a fulfillment class called “Warehouse” that had some methods called “CheckInvetoryOf(dynamic item)” – things start to make a bit more sense.
In the real world you would send in an interface here – probably ITrackable or something – that exposes a very very small subset of what could be used. It would work, but what if you changed your approach later and wanted the Warehouse to ship digital goods – something like downloads?
Your Warehouse class was probably fashioned after a brick and mortar – and making the shift to sending out digital downloads… OH NO!
But if you use dynamics – it’s easy. You could simply ask if the item has is an IDigitalGood (for instance) and handle it nicely.
So – the code you wrote is, yes, confusing. If you spend some time with Dynamic languages it will afford you the mental shift to make it not so confusing.
Oh – in terms of “Architecturally Wrong” to do what you did… who knows. If it’s confusing, that’s not good. If it makes testing hard – that’s triple not good. If you get laughed at, you might be on the right track 🙂