I am trying to implement object factory support with a read only object and would like to know the best way to populate it.
Hi,
This very similar to an editable object - you just leave out the state management commands.
Make sure to use the helper methods in ObjectFactory base class and use managed properties in your read-only object.
Sample her shown for a list:
public object Fetch(string criteria) { var list = (CustomerList)MethodCaller.CreateInstance(typeof(CustomerList)); // just sets up some mock data - could com from Xml,L2S, EF or othere sources unknown to the BO itself. var customers = new[] { new CustomerData {Id = 1, Name = "Baker, Jonathan"}, new CustomerData {Id = 2, Name = "Peterson, Peter"}, new CustomerData {Id = 3, Name = "Olsen, Egon"}, new CustomerData {Id = 4, Name = "Hansen, hans"} }; list.RaiseListChangedEvents = false; this.SetIsReadOnly(list, false); // tranform to my lists child type list.AddRange(customers.Select(p => new CustomerInfoFactory().GetCustomerInfo(p))); this.SetIsReadOnly(list, true); list.RaiseListChangedEvents = true; return list; }
public class CustomerInfoFactory : ObjectFactory { public Business.CustomerInfo GetCustomerInfo(DataEntitites.CustomerData data) { var customer = (CustomerInfo)MethodCaller.CreateInstance(typeof(CustomerInfo)); LoadProperty(customer, CustomerInfo.IdProperty, data.Id); LoadProperty(customer, CustomerInfo.NameProperty, data.Name); return customer; } }
Hi Johnny,
Thanks for that. But when I use the IntelliSense, somehow it is not pulling up the property name.
Ex: When I gave CustomerInfo & then a period, it shows the list of all methods (not properites). It shows the property only when I change the promerty to static (but the get method in that property is called by another staitic method)
Thanks,
Kris
Your code must make sure that the PropertyInfo is defined as public.
Hi Jonny,
This is what we are facing.
public static readonly PropertyInfo<System.Int32> _CustomerIDProperty = RegisterProperty<System.Int32>(p => p.CustomerID, "Customer I D");
public System.Int32 CustomerID
{
get { return GetProperty(_CustomerIDProperty); }
}
public class CustomerInfoFactory : ObjectFactory
{
public Business.CustomerInfo GetCustomerInfo(DataEntitites.CustomerData data)
{
var customer = (CustomerInfo)MethodCaller.CreateInstance(typeof(CustomerInfo));
LoadProperty(customer, CustomerInfo._CustomerIDProperty, data.Id);
But we want to refer "CustomerID" property instead of "_CustomerIDProperty"
Ex: LoadProperty(customer, CustomerInfo.CustomerID, data.Id);
I tried changing the actual property to static, but it won't work since the get operator is calling _CustomerIDProperty
Thanks
Hi,
You have 2 options:
You cannot use the actual property as a parameter to LoadProperty.
In the "old days" you could either use a "propertyname" or the PropertyInfo. In later versions IIRC there is only support for PropertyInfo as a parameter to LoadProperty.
I'm stuggling with the syntax of option 1. In this example I'm trying to set the value of AccountID in a read-only class with its definition below.
public AccountInfo Map(SafeDataReader reader)
{
var item = (AccountInfo)Methodcaller.CreateInstance(typeof(AccountInfo), true);
using (BypassPropertyChecks(item))
{
LoadProperty( item, PropertyInfo(<System.Int32> AccountInfo.AccountID), 123);
. . .
}
}
private static readonly PropertyInfo<System.Int32> _accountIDProperty = RegisterProperty<System.Int32>(p => p.AccountID, "Account ID");
[System.ComponentModel.DataObjectField(true, true)]
public System.Int32 AccountID
{
get { return GetProperty(_accountIDProperty); }
}
public AccountInfo Map(SafeDataReader reader)
{
var item = (AccountInfo)Methodcaller.CreateInstance(typeof(AccountInfo), true);
using (BypassPropertyChecks(item))
{
LoadProperty( item, AccountInfo._accountIDProperty, 123);
. . .
}
}
public static readonly PropertyInfo<System.Int32> _accountIDProperty = RegisterProperty<System.Int32>(p => p.AccountID, "Account ID");
You need to make the PropertyInfo in your BO public and then use it as the second parameter of LoadProperty.
I'm almost there, but am getting an error when referencing _accountIDProperty: "PetShop.Business.AccountInfo' does not contain a definition for '_accountIDProperty". I don't know what it means by definition given that the property definition is public static
namespace petshop.business
public static readonly PropertyInfo<System.Int32> _accountIDProperty = RegisterProperty<System.Int32>(p => p.AccountID, "Account ID");
[System.ComponentModel.DataObjectField(true, true)]
public System.Int32 AccountID
{
get { return GetProperty(_accountIDProperty); }
}
namespace Petshop.Data
public AccountInfo Map(SafeDataReader reader)
{
var item = (AccountInfo)Methodcaller.CreateInstance(typeof(AccountInfo), true);
using (BypassPropertyChecks(item))
{
LoadProperty(item, AccountInfo._accountIDProperty, reader.GetInt32("AccountID"));
LoadProperty(item, AccountInfo._uniqueIDProperty, reader.GetInt32("UniqueID"));
LoadProperty(item, AccountInfo._emailProperty, reader.GetString("Email"));
LoadProperty(item, AccountInfo._firstNameProperty, reader.GetString("FirstName"));
LoadProperty(item, AccountInfo._lastNameProperty, reader.GetString("LastName"));
LoadProperty(item, AccountInfo._address1Property, reader.GetString("Address1"));
LoadProperty(item, AccountInfo._address2Property, reader.GetString("Address"));
LoadProperty(item, AccountInfo._cityProperty, reader.GetString("City"));
LoadProperty(item, AccountInfo._stateProperty, reader.GetString("State"));
LoadProperty(item, AccountInfo._zipProperty, reader.GetString("Zip"));
LoadProperty(item, AccountInfo._countryProperty, reader.GetString("Country"));
LoadProperty(item, AccountInfo._phoneProperty, reader.GetString("Phone"));
}
return item;
}
With what you have posted here that should be compiling. Try deleting ._accountIDProperty in your Map method, and then type the . after AccountInfo again on that line and see if you can find the property in intellisense. Maybe its _accountIdProperty ? Or maybe yoiu just need to recompile the business project before it works. Also double check your references; I assume both projects are in the same solution, make sure your reference in the Data project is using a Project Reference to the Business project.
Are you using Resharper by any chance?
Hi,
And there is no point in having using BypassPropertyCheck with this code.
BypassPropertyCheck is only effective for Editable objects where you rather than use LoadPropery call the actual property setter in the object and want the SetProperty to work as LoadProperty.
Otherwise the code looks to be correct..
Make sure that your project references is not off (ex: dal references an assembly in bin folder and not the project in solution)
I had to add "using Csla.Reflection" before I could see MethodCaller in the item declaration. I got a good compile after that.
Thanks to all for the assist.
Hi Jonny, did you got my previous reply
Thanks,
Kris
Copyright (c) Marimer LLC