Anyone succeeded at injecting Interfaces into Entity Framework 4 Entities, using T4?
- by Ciel
Hello:
POCO sort of leaves me wanting: (how can I say I use DI/IoC, if the Repository is not the only place that is creating the entities?)...hence my desire to lock it down, get rid of the temptation of newing up POCOs or EntityObjects anywhere in the code, and just allowing entity interfaces above the Repository/Factory layer.
For a second there, I nearly thought I had it...was editing EF4's T4 in order to inject in an Interface def. Was going swimmingly, compiled and worked, until I got to the Associations...
I wrapped them with a ICollection, and renamed the underlying original collection with a prefix of Wrapped.
Unfortunately, when run, throws an error:
//The Member 'WrappedSubExamples' in the CLR type 'XAct.App.Data.Model.EF4.Example' is not present in the conceptual model type 'XAct.App.Data.Model.Entity.Example'.
var examples = context2.CreateObjectSet();
My T4 segment I used was (this may not work, as it's the longest code snippet I've ever posted here...sorry):
#region Generic Property Abstraction
<# if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) {#>
//XAct.App Generic Wrapper:
<#=code.SpaceAfter(NewModifier(navProperty))#><#=Accessibility.ForProperty(navProperty)#> ICollection<I<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>> <#=code.Escape(navProperty)#>
{
get {
if (_X<#=code.Escape(navProperty)# == null){
_X<#=code.Escape(navProperty)# =
new WrappedCollection,<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#(this.<#=(navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)?"Wrapped":""#<#=code.Escape(navProperty)#);
}
return _X<#=code.Escape(navProperty)#;
}
}
private ICollection _X<#=code.Escape(navProperty)#;
<# } else { #
<#=code.SpaceAfter(NewModifier(navProperty))#<#=Accessibility.ForProperty(navProperty)# I<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)# <#=code.Escape(navProperty)#
{
get {
return (I<#=code.Escape(navProperty)#)this.Wrapped<#=code.Escape(navProperty)#;
}
set {
this.Wrapped<#=code.Escape(navProperty)# = value as <#=code.Escape(navProperty)#;
}
}
<# } #
#endregion
which then wraps the original collection, renamed with the prefix 'Wrapped':
/// <summary>
/// <#=SummaryComment(navProperty)#>
/// </summary><#=LongDescriptionCommentElement(navProperty, region.CurrentIndentLevel) #>
[XmlIgnoreAttribute()]
[SoapIgnoreAttribute()]
[DataMemberAttribute()]
[EdmRelationshipNavigationPropertyAttribute("<#=navProperty.RelationshipType.NamespaceName#>", "<#=navProperty.RelationshipType.Name#>", "<#=navProperty.ToEndMember.Name#>")]
<#
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
<#=code.SpaceAfter(NewModifier(navProperty))#><#=Accessibility.ForProperty(navProperty)#> EntityCollection<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>> Wrapped<#=code.Escape(navProperty)#>
{
<#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get
{
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>");
}
<#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set
{
if ((value != null))
{
((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>", value);
}
}
}
<#
}
else
{
#>
<#=code.SpaceAfter(NewModifier(navProperty))#><#=Accessibility.ForProperty(navProperty)#> <#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#> Wrapped<#=code.Escape(navProperty)#>
{
<#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get
{
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value;
}
<#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set
{
((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value = value;
}
}
<#
string refPropertyName = navProperty.Name + "Reference";
if (entity.Members.Any(m => m.Name == refPropertyName))
{
// 6017 is the same error number that EntityClassGenerator uses.
Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6017", String.Format(CultureInfo.CurrentCulture,
GetResourceString("Template_ConflictingGeneratedNavPropName"),
navProperty.Name, entity.FullName, refPropertyName)));
}
#>
/// <summary>
/// <#=SummaryComment(navProperty)#>
/// </summary><#=LongDescriptionCommentElement(navProperty, region.CurrentIndentLevel)#>
[BrowsableAttribute(false)]
[DataMemberAttribute()]
<#=Accessibility.ForProperty(navProperty)#> EntityReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>> <#=refPropertyName#>
{
<#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get
{
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>");
}
<#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set
{
if ((value != null))
{
((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>", value);
}
}
}
<#
}
The point is...it bugs out. I've tried various solutions...none worked. Any ideas -- or is this just a wild goose chase, and time to give it up?