Upgrading Unity to 5.11.1 - unity-container

I'm trying do upgrade Unity from version 3.0.1304.1 to the latest, 5.11.1. Unsurprisingly, there are some issues (3.0.1304.1 is quite old). The code below accomplished two things:
Use a ContainerControlledLifetimeManager for all classes deriving from some base class X, without specifying that for every class derived from X.
Use the default constructor when resolving for all classes deriving from base class Y, without specifying that for every class derived from Y.
Unity documentation is scarce nowadays, and lacks examples. I've read the upgrade notes and regular documentation but I can't make this work with the new version.
So far I have:
Replaced IConstructorSelectorPolicy with ISelect<ConstructorInfo>
Replaced IBuilderContext with BuilderContext (or ref BuilderContext in the PreBuildUp function)
But what to do with the LifetimeManagerFactory? Should I derive IOCConstructorSelectorPolicy from ISelect<ConstructorInfo> and should IOCConstructorSelectorPolicy.SelectConstructor then be replaced by Select (as per the ISelect interface) and how to implement this Select function?
I know this is a very long shot, and I'll post this on the unity github as well (as a request for documentation of sorts), but hopefully there is someone who can give me some pointers.
/// <summary>
/// This class merely exists for readability: avoid having to write the class it derives from.
/// </summary>
public class IOCConfigLifetimeExtension : DefaultLifetimeManagerExtension<ContainerControlledLifetimeManager, X>
{}
/// <summary>
/// An IOC strategy to use a specific LifetimeManager (<typeparamref name="TLifetimeManager"/>) for subclasses of <typeparamref name="TBaseClass"/>.
/// </summary>
public class DefaultLifetimeManagerExtension<TLifetimeManager, TBaseClass> : UnityContainerExtension where TLifetimeManager : LifetimeManager, new()
{
protected override void Initialize()
{
var theFactory = new LifetimeManagerFactory(Context, typeof(TLifetimeManager));
Context.Strategies.Add(new DefaultLifetimeManagerStrategy(theFactory, TypePredicate), UnityBuildStage.TypeMapping);
}
private bool TypePredicate(Type type)
{
return typeof (TBaseClass).IsAssignableFrom(type);
}
}
public class DefaultLifetimeManagerStrategy : BuilderStrategy
{
public DefaultLifetimeManagerStrategy(LifetimeManagerFactory factory, Predicate<Type> typePredicate)
{
mFactory = factory;
mTypePredicate = typePredicate;
}
public override void PreBuildUp(IBuilderContext context)
{
if (context.Existing == null) {
var theLifetime = context.Policies.GetNoDefault<ILifetimePolicy>(context.BuildKey, false);
if (theLifetime == null && mTypePredicate(context.BuildKey.Type)) {
theLifetime = mFactory.CreateLifetimePolicy();
context.PersistentPolicies.Set(theLifetime, context.BuildKey);
}
}
}
private readonly LifetimeManagerFactory mFactory;
private readonly Predicate<Type> mTypePredicate;
}
/// <summary>
/// A Unity extension that prioritizes the default constructor for classes derived of Y when available, otherwise the default resolve method is used.
/// </summary>
public class IOCExtension : UnityContainerExtension
{
protected override void Initialize()
{
var theDefaultConstructorSelectorPolicy = Context.Policies.Get<IConstructorSelectorPolicy>(null);
Context.Policies.SetDefault<IConstructorSelectorPolicy>(new IOCConstructorSelectorPolicy(theDefaultConstructorSelectorPolicy));
}
public class IOCConstructorSelectorPolicy : IConstructorSelectorPolicy
{
public IOCConstructorSelectorPolicy(IConstructorSelectorPolicy defaultConstructorSelectorPolicy)
{
mDefaultConstructorSelectorPolicy = defaultConstructorSelectorPolicy;
}
public SelectedConstructor SelectConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination)
{
Type theType = context.BuildKey.Type;
if (typeof(DataNode).IsAssignableFrom(theType)) {
ConstructorInfo theDefaultConstructorInfo = theType.GetConstructor(Type.EmptyTypes);
if (theDefaultConstructorInfo != null && theDefaultConstructorInfo.IsPublic) {
return new SelectedConstructor(theDefaultConstructorInfo);
}
}
return mDefaultConstructorSelectorPolicy.SelectConstructor(context, resolverPolicyDestination);
}
private readonly IConstructorSelectorPolicy mDefaultConstructorSelectorPolicy;
}
}

Related

Xamarin Forms overriding OnAppearing causes app to crash

I am trying to do a simple override and load some data when my page loads, I am using the following code in the code behind page.
namespace XYZ
{
public partial class MainPage : ContentPage
{
private Label results;
private Label groupResults;
public MainPage()
{
InitializeComponent();
results = new Label();
groupResults = new Label();
}
protected override void OnAppearing()
{
base.OnAppearing();
storeIdTxt.Text = Settings.StoreIdSetting;
}
}
}
If I uncomment the override things works just fine, the error I am getting seems to be a generic one attached here
my settings class is fairly simple as follows
using System;
using System.Collections.Generic;
using System.Text;
using Plugin.Settings;
using Plugin.Settings.Abstractions;
namespace NWMPosNG.Helpers
{
/// <summary>
/// This is the Settings static class that can be used in your Core solution or in any
/// of your client applications. All settings are laid out the same exact way with getters
/// and setters.
/// </summary>
public static class Settings
{
private static ISettings AppSettings
{
get
{
return CrossSettings.Current;
}
}
#region Setting Constants
private const string SettingsKey = "settings_key";
private static readonly string SettingsDefault = string.Empty;
private const string StoreId = null;
private static readonly string StoreIdDefault = "0";
#endregion
public static string GeneralSettings
{
get
{
return AppSettings.GetValueOrDefault(SettingsKey, SettingsDefault);
}
set
{
AppSettings.AddOrUpdateValue(SettingsKey, value);
}
}
public static string StoreIdSetting
{
get
{
return AppSettings.GetValueOrDefault(StoreId, StoreIdDefault);
}
set
{
AppSettings.AddOrUpdateValue(StoreId, value);
}
}
}
}
I narrowed down the issue to when I access the saved data using
storeIdTxt.Text = Settings.StoreIdSetting;
But I don't understand why that causes the crash.
You are using the Settings Plugin from James Montemagno. Which is pretty much a KeyValuePair that is stored on the local device across sessions.
In your case:
AppSettings.GetValueOrDefault(StoreId, StoreIdDefault);
Translates to:
AppSettings.GetValueOrDefault(null, "0");
Which crashes because 'null' can't be a key. That's why setting the key (StoreId) prevents the crash from happening.
This line was the culprit
private const string StoreId = null;
I don't really understand why but setting this to a non NULL value makes the crash go away

MSUnity - Registering Types - Generic Abstract Class

I've just implemented the Translator pattern discussed here and here like so...
ITranslator interface...
public interface ITranslator
{
bool CanTranslate(Type targetType, Type sourceType);
bool CanTranslate<TTarget, TSource>();
object Translate(Type targetType, object source);
TTarget Translate<TTarget>(object source);
}
Translator.cs...
public abstract class Translator<TBusinessEntity, TServiceEntity> : ITranslator where TBusinessEntity : class
where TServiceEntity : class
{
public bool CanTranslate(Type targetType, Type sourceType)
{
return (targetType == typeof(TBusinessEntity) && sourceType == typeof(TServiceEntity)) ||
(targetType == typeof(TServiceEntity) && sourceType == typeof(TBusinessEntity));
}
public bool CanTranslate<TTarget, TSource>()
{
return CanTranslate(typeof (TTarget), typeof (TSource));
}
public TTarget Translate<TTarget>(object source)
{
return (TTarget)Translate(typeof(TTarget), source);
}
public object Translate(Type targetType, object source)
{
if (targetType == typeof(TBusinessEntity))
return ServiceToBusiness((TServiceEntity)source);
if (targetType == typeof(TServiceEntity))
return BusinessToService((TBusinessEntity)source);
throw new System.ArgumentException("Invalid type passed to Translator", "targetType");
}
protected abstract TServiceEntity BusinessToService(TBusinessEntity value);
protected abstract TBusinessEntity ServiceToBusiness(TServiceEntity value);
protected abstract List<TServiceEntity> BusinessToService(List<TBusinessEntity> valueList);
protected abstract List<TBusinessEntity> ServiceToBusiness(List<TServiceEntity> valueList);
}
Here is my StudentFeeTranslator class that implements the Translator abstract methods...
public class StudentFeeTranslator : Translator<StudentFee, StudentFeeType>
{
#region Overrides of Translator<StudentFee,StudentFeeType>
protected override StudentFeeType BusinessToService(StudentFee value)
{
return new
StudentFeeType
{
StudentFeeId = value.StudentFeeRefId,
FeeId = value.FeeRefId,
StudentId = value.StudentRefId,
SchoolId = value.SchoolRefId,
FeeDate = value.AssessmentDate,
FeeAmount = value.AssessmentAmount,
Balance = value.UnpaidBalance,
FeeTypeId = value.FeeType,
Description = value.FeeDescription
};
}
protected override StudentFee ServiceToBusiness(StudentFeeType value)
{
return new
StudentFee
{
StudentFeeRefId = value.StudentFeeId,
FeeRefId = value.FeeId,
StudentRefId = value.StudentId,
SchoolRefId = value.SchoolId,
AssessmentDate = value.FeeDate,
AssessmentAmount = value.FeeAmount,
UnpaidBalance = value.Balance,
FeeType = (Byte)value.FeeTypeId,
FeeDescription = value.Description
};
}
protected override List<StudentFeeType> BusinessToService(List<StudentFee> valueList)
{
return valueList.Select(BusinessToService).ToList();
}
protected override List<StudentFee> ServiceToBusiness(List<StudentFeeType> valueList)
{
return valueList.Select(ServiceToBusiness).ToList();
}
#endregion
}
Next is my StudentFeeService class minus the irrelevant methods. Notice the Translator property tagged for injection...
public partial class StudentFeeService : IStudentFeeService
{
#region Public Members
[Dependency]
public ITranslator Translator { get; set; }
#endregion
#region Private Methods
private List<StudentFeeType> ConvertStudentFeeListToListOfStudentFeeTypes(List<StudentFee> studentFees)
{
return Translator.Translate<List<StudentFeeType>>(studentFees);
}
#endregion
}
Finally, here is the code snippet of my attempt to register the Translator class with my Unity container...
container.RegisterType(typeof (ITranslator), typeof (Translator<,>));
This attempt failed. My question is how can I register a generic abstract class with a Unity container? FYI I'm using MSUnity 2.0.
You are trying to map a non-generic interface to an open generic type. How should Unity (or any other container) guess if your service needs a StudenFeeTranslator or a RentalFeeTranslator? Both implement ITranslator and that is all the container can see.
You can register all of your concrete implementations of ITranslator giving them individual names. This is something all containers support. And then make Unity inject that specific dependency into the Translator property of your service. Something like
container.RegisterType(typeof(ITranslator), typeof(StudentFeeTranslator), "StudentFee");
container.RegisterType(typeof(ITranslator), typeof(RentalFeeTranslator), "RentalFee");
container.RegisterType(typeof(IStudentFeeService), typeof(StudentFeeService),
new InjectionProperty("Translator", new ResolvedParameter<ITranslator>("StudentFee")));
That is a lot of repetetive code though.
Unity does not come with registration conventions out-of-the-box. But the TecX project contains an enhanced configuration engine that would allow you to do something like this:
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.Scan(
scanner =>
{
scanner.AddAllImplementationsOf(typeof(ITranslator);
scanner.AssembliesFromApplicationBaseDirectory();
});
container.AddExtension(builder);
This registers all implementations of ITranslator with the name of the implementing class (e.g. the name for StudentFeeTranslator would be StudentFeeTranslator) in one go.
If you make your interface generic it would be easier to inject into the property. Matching ITranslator<X, Y> to an implementation thereof is not really hard to do.

Attaching MetaData class to ADO.NET Entity Data model classes

I have a problem attaching metadata class to ADO.NET entity data model generated classes.
According to the following links...
http://blogs.microsoft.co.il/blogs/gilf/archive/2011/01/20/adding-metadata-to-entities-in-the-data-model.aspx
http://msdn.microsoft.com/en-us/library/cc679243.aspx
http://goneale.com/2009/03/04/using-metadatatype-attribute-with-aspnet-mvc-xval-validation-framework/
http://davidhayden.com/blog/dave/archive/2008/01/06/ASPNETDynamicDataTutorialBuddyMetadataProviderCustomMetadataProviders.aspx
http://davidhayden.com/blog/dave/archive/2008/05/15/DynamicDataWebsitesScaffoldTableScaffoldColumnAttributes.aspx
I created a metadata class to add some Attributes to properties. I could add this attributes to properties in generated classes and It works but I wanted to avoid loosing this attributes every time I have to update and recreate my ADO.NET entity data model.
My question is, what am I doing wrong ? Why in runtime properties does not have my custom attributes ?
This is a part of generated data class
[EdmEntityTypeAttribute(NamespaceName="HelpMeHowModel", Name="Article")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
[MetadataType(typeof(ArticleMetaData))]
public partial class Article : EntityObject
{
#region Primitive Properties
/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.Boolean IsPublished
{
get
{
return _IsPublished;
}
set
{
OnIsPublishedChanging(value);
ReportPropertyChanging("IsPublished");
_IsPublished = StructuralObject.SetValidValue(value);
ReportPropertyChanged("IsPublished");
OnIsPublishedChanged();
}
}
private global::System.Boolean _IsPublished;
partial void OnIsPublishedChanging(global::System.Boolean value);
partial void OnIsPublishedChanged();
...
.. and this is my metadata class
public class ArticleMetaData
{
#region Primitive Properties
[BoolFunction(BoolFunction.ThreeStateRadioButton)]
public global::System.Boolean IsPublished { get; set; }
For everybody looking for the solution for the same problem...
Adding custom attributes to partial MetadataType class is possible and it works but there is a little problem.
Using
PropertyInfo pi;
pi.GetCustomAttributes(...)
will get the Attributes from the main class only and not from the class used as MetadataType.
Based on solution explained here
Attribute.IsDefined doesn't see attributes applied with MetadataType class
I created two extension methods for PropertyInfo class to get all attributes.
namespace FAIN.Framework.Commons
{
public static class PropertyInfoEx
{
public static object[] GetAllCustomAttributes(this PropertyInfo pi, bool inherit)
{
return GetAllCustomAttributes(pi, null, inherit);
}
/// <summary>
/// Get Custom Attributes + attributes added in MetadataType
/// </summary>
/// <param name="pi"></param>
/// <param name="attributeType"></param>
/// <param name="inherit"></param>
/// <returns></returns>
public static object[] GetAllCustomAttributes(this PropertyInfo pi, Type attributeType, bool inherit)
{
if (pi == null) return null;
List<object> allAttributes = new List<object>();
object[] attributes = null;
if (attributeType != null)
{
attributes = pi.GetCustomAttributes(attributeType, inherit);
}
else
{
attributes = pi.GetCustomAttributes(inherit);
}
allAttributes.AddRange(attributes);
// search all the Metadata of the class declaring the property to get all CustomAttributes if there are any
MetadataTypeAttribute[] metadataTypes = pi.DeclaringType.GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().ToArray();
foreach (MetadataTypeAttribute metadata in metadataTypes)
{
if (metadata != null)
{
PropertyInfo[] properties = metadata.MetadataClassType.GetProperties();
PropertyInfo propertyInfo = properties.Where(p => p.Name == pi.Name).FirstOrDefault();
if (propertyInfo != null)
{
if (attributeType != null)
{
attributes = propertyInfo.GetCustomAttributes(attributeType, inherit);
}
else
{
attributes = propertyInfo.GetCustomAttributes(inherit);
}
allAttributes.AddRange(attributes);
}
}
}
return allAttributes.ToArray();
}
}
}

Which of the two design patterns should I implement in a 3-tier Asp.Net application?

I’m trying to decide which of the two factory patterns I should use in my Asp.Net applications:
1 : All DAL providers derive from same abstract base class DepartmentsProvider, which defines public interface of the class ( all the necessary CRUD methods for which derived classes (providers ) provide a concrete implementation ). BLL layer instantiates correct provider by calling DepartmentsProvider.Instance:
public abstract class DepartmentsProvider
{
static private DepartmentsProvider _instance = null;
/// <summary>
/// Returns an instance of the provider type specified in the config file
/// </summary>
static public DepartmentsProvider Instance
{
get
{
if (_instance == null)
_instance = (DepartmentsProvider)Activator.CreateInstance(
Type.GetType(Settings.Departments.ProviderType));
return _instance;
}
}
public abstract List<Department> GetDepartments ();
}
/// Concrete provider
public class SqlDepartmentsProvider : DepartmentsProvider
{
public override List<Department> GetDepartments()
{
using (SqlConnection cn = new SqlConnection(this.ConnectionString))
{...}
}
}
2 :
public class DepartmentsProvider
{
static private DbProviderFactory _instance = null;
/// <summary>
/// Returns an instance of the FactoryProvider type specified in the config file
/// </summary>
static public DbProviderFactory Instance
{
get
{
if (_instance == null)
_instance = (DepartmentsProvider)Activator.CreateInstance(
Type.GetType(Settings.Departments.ProviderType));
return _instance;
}
}
public static List<ForumDetails> GetDepartments()
{
DbConnection cn = Instance.CreateConnection();
...
}
}
In first case we implement new provider by deriving from DepartmentsProvider class, while in second case new provider is implemented by deriving from DBProviderFactory.
What are pros and cons of each implementation?
Much appreciated
Like RPM1984 I would suggest looking at the repository pattern and dependency injection.
You wouldn't want to use a singleton here as the connections may remain open and you may run into unforeseen issues.

Grails bind request parameters to enum

My Grails application has a large number of enums that look like this:
public enum Rating {
BEST("be"), GOOD("go"), AVERAGE("av"), BAD("ba"), WORST("wo")
final String id
private RateType(String id) {
this.id = id
}
static public RateType getEnumFromId(String value) {
values().find {it.id == value }
}
}
If I have a command object such as this:
class MyCommand {
Rating rating
}
I would like to (for example) automatically convert a request parameter with value "wo" to Rating.WORST.
The procedure for defining custom converters is described here (in the context of converting Strings to Dates). Although this procedure works fine, I don't want to have to create a class implementing PropertyEditorSupport for each of my enums. Is there a better alternative?
I found a solution I'm pretty happy with.
Step 1: Create an implementation of PropertyEditorSupport to convert text to/from the relevant Enum
public class EnumEditor extends PropertyEditorSupport {
private Class<? extends Enum<?>> clazz
public EnumEditor(Class<? extends Enum<?>> clazz) {
this.clazz = clazz
}
public String getAsText() {
return value?.id
}
public void setAsText(String text) {
value = clazz.getEnumFromId(text)
}
}
Step 2: Define a class that registers EnumEditor as a converter for the various enum classes. To change the list of enum classes that are bindable by id, just modify BINDABLE_ENUMS
public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
private static final String REQUIRED_METHOD_NAME = 'getEnumFromId'
// Add any enums that you want to bind to by ID into this list
private static final BINDABLE_ENUMS = [Rating, SomeOtherEnum, SomeOtherEnum2]
public void registerCustomEditors(PropertyEditorRegistry registry) {
BINDABLE_ENUMS.each {enumClass ->
registerEnum(registry, enumClass)
}
}
/**
* Register an enum to be bound by ID from a request parameter
* #param registry Registry of types eligible for data binding
* #param enumClass Class of the enum
*/
private registerEnum(PropertyEditorRegistry registry, Class<? extends Enum<?>> enumClass) {
boolean hasRequiredMethod = enumClass.metaClass.methods.any {MetaMethod method ->
method.isStatic() && method.name == REQUIRED_METHOD_NAME && method.parameterTypes.size() == 1
}
if (!hasRequiredMethod) {
throw new MissingMethodException(REQUIRED_METHOD_NAME, enumClass, [String].toArray())
}
registry.registerCustomEditor(enumClass, new EnumEditor(enumClass))
}
}
Step 3: Make Spring aware of the registry above by defining the following Spring bean in grails-app/conf/spring/resources.grooovy
customPropertyEditorRegistrar(CustomPropertyEditorRegistrar)
So the default Databinding binds on the Enum name and not a separately defined property of the Enum. You can either create your own PropertyEditor as you have mentioned or do a work-around similar to this:
class MyCommand {
String ratingId
Rating getRating() {
return Rating.getEnumFromId(this.ratingId)
}
static constraints = {
ratingId(validator:{val, obj -> Rating.getEnumFromId(val) != null })
}
}

Resources