hi guys,
I want to modify attributes (f.e. datasourcecriteria) in the CustomizeTypesInfo override.
I know I can add attributes and members etc but how can I alter existing attributes?
I want to use this mechanism to override certain attributes for descendant properties.
This is a way to apply different attribute settings in decendant classes for properties resided at ancestor level,
a thing that isn't possible at the moment.
Thx
Arjan
Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.
Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.
Hello Arjan,
To change the value of the existing attribute, you should remove the old attribute via the XafMemberInfo.RemoveAttribute method, and add a new one via the AddAttribute method.
Thanks,
Anatol
Hi Anatol,
I tried that (btw I'm using DC) but with no luck.
f.e. I've the following
[DomainComponent]
[DefaultClassOptions]
public interface ICustomerType
{
string Code { get; set; }
}
[DomainComponent]
public interface ICustomer
{
[DataSourceCriteria("Code = 'Default'")]
ICustomerType CustomerType { get; set; }
string Name { get; set; }
}
[DomainComponent]
[DefaultClassOptions]
public interface ICustomerExt: ICustomer
{
}
and
public override void CustomizeTypesInfo(DevExpress.ExpressApp.DC.ITypesInfo typesInfo)
{
base.CustomizeTypesInfo(typesInfo);
var c = XafTypesInfo.XpoTypeInfoSource.XPDictionary.GetClassInfo(typeof(ICustomerExt));
var m = c.FindMember("CustomerType");
m.RemoveAttribute(typeof(DataSourceCriteriaAttribute));
m.AddAttribute(new DataSourceCriteriaAttribute("Code='Customer'"));
XafTypesInfo.Instance.RefreshInfo(typeof(ICustomerExt));
}
The attribute will be removed on XPDixtionary level so that part works.
Only when I want to refresh using RefreshInfo the changes won't be refreshed in the typesinfo.
The result is that the old datasourcecriteria is still there…
(maybe this is DC specific?)
Hello Arjan,
Please try to use the following code to accomplish your task:
public override void Setup(XafApplication application) { base.Setup(application); if (!XafTypesInfo.IsInitialized) { XafTypesInfo.Instance.RegisterEntity("CustomerType", typeof(ICustomerType)); XafTypesInfo.Instance.RegisterEntity("Customer", typeof(ICustomerExt)); } } public override void CustomizeTypesInfo(DevExpress.ExpressApp.DC.ITypesInfo typesInfo) { base.CustomizeTypesInfo(typesInfo); var c = typesInfo.FindTypeInfo(typeof(ICustomerExt)); var m = c.FindMember("CustomerType"); ((XafMemberInfo)m).RemoveAttribute(((XafMemberInfo)m).FindAttribute<DataSourceCriteriaAttribute>(true)); m.AddAttribute(new DataSourceCriteriaAttribute("Code='Customer'")); XafTypesInfo.Instance.RefreshInfo(typeof(ICustomerExt)); }
Note that it will not be possible to use different DataSourceCriteria in different ICustomer descendants as the CustomerType property belongs to the parent interface and will be changed in all descendants.
Thanks,
Anatol
hi Anatol,
thx for the anwser. The outcome is now as expected.
There is one strange thing though. Removing the attribute will remove the datasourcecriteria from the member.
Add the new attribute again will add the new attribute as expected but also the old one again ("Code='Default').
Somehow this doesn't affect the endresult ??
So I'm not quite sure if it works in all scenario's.
Hello Arjan,
I have not managed to reproduce this issue using classes you provided. Please see my test project in the attachment.
I received the result you described when I tried to change the DataSourceCriteria attribute of several descendants. As I mentioned, my solution does not support this scenario. If you need to implement it, please describe your real task in greater detail.
Thanks,
Anatol
hi Anatol,
thx for the quick and clear response.
you're completely right. It's is not possible to remove an existing datasourcecriteria from an ancestor member (too bad)
Maybe if suggestion S37289 is implemented? Do you know the (internal) status of this suggestion?
I would make DC a lot more powerfull.
A little background:
I'm making a lot of DC modules for other developers which they use to build the end-applications.
This kind of functionality gives them a lot of flexibility in modeliing the business logic
thx
Arjan
Hello Arjan,
This suggestion is unlikely to be implemented soon. If I understand your scenario correctly, the following suggestion would be more useful for you: DC - Provide the capability to filter domain components by their type. By the way, it is already possible to filter domain components by their type using the ObjectType field if they are registered in the AsAlias mode. For example:
XafTypesInfo.Instance.RegisterEntity("CustomerBase", typeof(ICustomer)); XafTypesInfo.Instance.RegisterEntity("Customer1", typeof(ICustomerExt1)); XafTypesInfo.Instance.RegisterEntity("Customer2", typeof(ICustomerExt2)); ... IList<ICustomer> list = ObjectSpace.GetObjects<ICustomer>(CriteriaOperator.Parse("ObjectType.TypeName = 'Customer2'"));
It is also possible to set DataSourceCriteria for descendants via the Model Editor as shown in the attached screenshot.
Thanks,
Anatol
hi Anatol,
I've created a functional framework using DC. This framework makes use of relatively small interfaces that can be used as building blocks.
Therefore the framework relies on multiple inheritance heaviliy and also the application build on top of the framework.
As a result I scarcely make use of the AsAlias function as it has some restrictions.
( I can send you an example of my framework structure)
My goal is to create functionality in code to override some attributes defined in ancestor entitties (interfaces) as you can see in my previous example.
Somehow there must be a way to remove attributes from ancestor properties or replace them with new ones.
It's basically the same functionality that's supported via the application model (as you said) but than doing it in code.
(my goal is to define as much as possible in the domain model centralizing my logic).
Hello Arjan,
Currently, you can indicate that you want to change the descendant's DataSourceCriteria using a custom attribute applied to the derived domain component. Then, you can customize the Application Model in code to write settings passed to this attribute to the model's DataSourceCriteria property. You can find a sample in the How to implement a custom attribute to customize the Application Model Code Central example.
Thanks,
Anatol
hi Anatol,
thx for the response.
I've tried the following using the Model update approach.
In ModuleBase class
public override void AddGeneratorUpdaters(ModelNodesGeneratorUpdaters updaters) {
base.AddGeneratorUpdaters(updaters);
updaters.Add(new MyUpdater());
public class MyUpdater : ModelNodesGeneratorUpdater<ModelBOModelClassNodesGenerator>
{
public override void UpdateNode(ModelNode node)
{
var c = ((IModelBOModel)node).FirstOrDefault(x => x.Name == "Solution35.Module.BOModel.ICustomerExt");
if (c != null)
{
var p = c.FindMember("CustomerType");
p.DataSourceCriteria = "Code = 'Customer'";
}
}
}
Is this the way to go? As I can see it works correctly in the UI.
BTW I tried to override reference properties in DC but with no luck (like in E1754)
Because if I can override reference properties I've no problem anymore. I can also override attributes
in descendant interfaces.
Hello Arjan,
Yes, this approach should work.
>> BTW I tried to override reference properties in DC but with no luck (like in E1754)
Please note that when you use the approach demonstrated in the E1754 example, you do not actually override the base classes' property. XPO does not support this. Instead, you create new properties with the same name in descendant classes, and hide the base class' property. The same result can be achieved by introducing a new property in the descendant class.
Thanks,
Anatol
Hi Anatol,
Yes, override is not the right word. But can you confirm that
using the 'new' approach in DC isn't supported?
thx
Arjan
Hello Arjan,
It is supported in the AsAlias mode. I have tested the following code:
[DomainComponent] public interface ICustomer { [DataSourceCriteria("Code = 'Default'")] ICustomerType CustomerType { get; set; } string Name { get; set; } } [DomainComponent] [DefaultClassOptions] public interface ICustomerExt1 : ICustomer { [DataSourceCriteria("Code = 'Customer'")] new ICustomerType CustomerType { get; set; } } [DomainComponent] [DefaultClassOptions] public interface ICustomerExt2 : ICustomer { [DataSourceCriteria("Code = 'Custom'")] new ICustomerType CustomerType { get; set; } }
and found that it works.
Thanks,
Anatol
Hi Anatol,
OK. thx for the answer.
As i stated before
"As a result I scarcely make use of the AsAlias function as it has some restrictions. "
Can you tell me if the possibility to use the "new" keyword in descendants (not aliasmode)
will be supported?
It would be in line with the whole re-usability concept of DC.
Hello Arjan,
We do not plan to support this scenario as it looks more like a hack and does not fit the common concept. We believe that it will be enough to redefine the DataSourceCriteria in the Application Model.
Thanks,
Anatol
thx for the answer.
I agree with you about overrulling attributes in code…
but for the other discussion…
I still cannot see why the "new" approach is supported by domain objects and not by DC (not in alias mode)?
Hello Arjan,
This approach intentionally wasn't supported by domain objects. The fact that it works is a useful side-effect, but we did not plan to provide this capability. If you try to use any XPO-specific attribute in the same way, you will see that it does not work.
For DC, we are not going to support this scenario on purpose. Are you experiencing any difficulty with a solution that involves the use of the Application Model?
Thanks,
Anatol
hi Anatol,
No not at the moment. I've created my own custom attributes on class level that will be used to assign different kinds of attributes
on ancestor properties. (using generators for this).
So, my co-developers are able to assign their own overrulling attributes in descendant interfaces. They want to have this kind of flexibility
and, at the same time, I can define as much as default behaviour in my base layer.
This works great in practice (for as I can see now!) Maybe this approach could be an addition in the standard XAF framework?
The only drawback of this approach is that I need to have a XAF implementation for this to be able to work.
thx Arjan
Hello Arjan,
Would you please describe your suggestion in greater detail? What do you think we should add to XAF to make it easier to use the approach you have used?
Thanks,
Anatol
hi Anatol,
I'll give you an example
I've created a custom attribute for DataSourceCriteria like this:
[AttributeUsage(AttributeTargets.Interface)]
public class MyDataSourceCriteria : Attribute
{
public MyDataSourceCriteria(string propertyName, string criteria)
: base()
{
PropertyName = propertyName;
Criteria = criteria;
}
public string Criteria { get; set; }
public string PropertyName { get; set; }
}
This attribute I can apply on descendant interfaces specifying the ancestor property I want to apply the criteria on.
f.e.
[DomainComponent]
public interface ICustomer
{
[DataSourceCriteria("Code='Default'")]
ICustomerType CustomerType { get; set; }
[RuleRequiredField("", DefaultContexts.Save)]
string Name { get; set; }
}
[DomainLogic(typeof(ICustomer))]
public class ICustomerLogic
{
}
[DomainComponent]
[DefaultClassOptions]
[MyDataSourceCriteria("CustomerType", "Code='Customer'")]
public interface ICustomerExt: ICustomer
{
}
Than I define a new ModelNodesGeneratorUpdater where I retrieve all the interfaces having the MyDataSourceCriteria attributes.
Foreach attribute, I lookup the property in the BOModel and applying the criteria to it.
I do the same for other attributes and for most of the validationrules.
My suggestion is to integrate those custom attributes and how they are applied into the XAF framework. It is just a way of manipulating the application model
from within code rather than editing the application model via the designer.
This is more convenient while having as much as logic and references in code only.
Centralizing logic in code is preffered to fragmentation (some logic in app model, some logic in code)
Is that imaginable?
thx Arjan
Hello Arjan,
Thank you for the clarification. I have discussed the proposed functionality with our developers and we have decided to create a corresponding suggestion: DC - Provide the capability to redefine model settings of parent properties in descendants. It will unlikely be implemented in the next release because:
a) it is already possible to accomplish this task via ModelEditor and GeneratorUpdater;
b) there is the possibility that Domain Components will be changed, so that this functionality will be no longer supported.
We need to track the number of similar requests and implement the final version of Domain Components. After that, we will decide whether to implement the mentioned suggestion or not.
Thanks,
Anatol
hi Anatol,
Many thx for making the suggestion.
In what way will DC change? As I said, I've created a pretty large (functional) framework that relies on DC completely making use of
multiple-inheritance all the time. Can you reassure me that this won't break in the future?
thx
Arjan
Hello Arjan,
Currently we are working on TypesInfo and model generation for domain components. In the current state of affairs it is difficult to say whether any breaking changes will be introduced, but we will certainly try to avoid them.
Thanks,
Anatol
many thx for your help Aanatol,
(I'm a little bit reassured now)