Note that there are some explanatory texts on larger screens.

plurals
  1. POProject structure for EF/Silverlight application
    primarykey
    data
    text
    <p>I am currently working on finding a good project structure for a 3-tier solution to avoid unnecessary work in a new project.</p> <p>The project will consist of a core product which has</p> <ul> <li>model project which holds the EF code first models</li> <li>project which has the business logic and communication logic on the server</li> <li>repository project on the client</li> <li>silverlight project with views and view models (would like to use caliburn.micro here)</li> </ul> <p>The problem is now that a customer could have some special requirements which could lead to changes in all the above projects. So my thought was that I could just use the base structure and create the same structure for a customer. If there are no changes I would just have empty classes that just extend the base class and add nothing.</p> <p>Which brings me to the following problems:</p> <ul> <li>Is it a problem in Entity Framework (code first) to have base classes in one project (which is already fully functional) and have another project which may extend the model classes with new field?</li> <li>Is it a problem in XAML to change a user control? For example if I have a user control that consists of five textboxes in my core and I want to change the second box to a radio button, but nothing else.</li> </ul> <p>I will also accept changes to the project structure, if there is a better way to handle customer specific changes.</p> <p><strong>Edit: I will probably use the following approach to solve the problem.</strong></p> <p><strong>Entity Framework:</strong></p> <p>With code first it seems to be possible to have one model project extend another project. This means I could write something like:</p> <pre><code>public class CoreAddress{ [Key] public int AdrId{get; set;} public string Street {get;set;} } public class CustomerAddress : CoreAddress{ public string StreetNumber {get; set;} } </code></pre> <p>Only thing that is needed in order to make that work is a line inside the DbContext:</p> <pre><code>(this as IObjectContextAdapter).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(&lt;entity from other assembly&gt;).Assembly); </code></pre> <p><strong>XAML</strong></p> <p>To get a similar behavior in XAML I had to use Caliburn.Micro (in combination with MEF) which is a great help here.</p> <p>I would create UserControls that include ContentControl elements which are dynamically fetched by using MEF. That means I have again a core project with all the views and ViewModels. If I need to exchange a special control somewhere for a customer I change the control to a ContentControl and create a core view and ViewModel for it (which is the same as it was before the change request). This ViewModel for the ContentControl is annoted with an export interface and ExportMetadata to set a priority of 1. Now I create another project with another UserControl that has some other control instead of the core control and annotate it again as an export with the same interface but set my priority higher and so the customer specific control is loaded.</p> <p>Short example for this:</p> <p>Main user control and view model:</p> <pre><code>&lt;UserControl x:Class="SilverlightApplication5.TestView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"&gt; &lt;Grid x:Name="LayoutRoot" Background="White"&gt; &lt;StackPanel&gt; &lt;ContentControl x:Name="Item"/&gt; &lt;TextBox x:Name="TextItem" Text="asdf"/&gt; &lt;/StackPanel&gt; &lt;/Grid&gt; &lt;/UserControl&gt; public class TestViewModel : Screen { private object viewModel; private Lazy&lt;IMyViewModel, IPluginMetadata&gt;[] _orderEditorFactory; [ImportMany(typeof(IMyViewModel), AllowRecomposition = true)] public Lazy&lt;IMyViewModel, IPluginMetadata&gt;[] OrderEditorFactory { get { return _orderEditorFactory; } set { _orderEditorFactory = value; Item = _orderEditorFactory.OrderByDescending(lazy =&gt; lazy.Metadata.Priority).First().Value; } } private object _item; public object Item { get { return _item; } set { _item = value; NotifyOfPropertyChange(() =&gt; Item); } } } </code></pre> <p>Core Control:</p> <pre><code>&lt;UserControl x:Class="SilverlightClassLibrary2.MainControlView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"&gt; &lt;StackPanel&gt; &lt;TextBlock x:Name="Test" Text="Text from Core control"/&gt; &lt;/StackPanel&gt; &lt;/UserControl&gt; [Export(typeof (IMyViewModel))] [ExportMetadata("Name", "Pluginc")] [ExportMetadata("Priority", 30)] public class MainControlViewModel : Screen, IHarnessAware, IMyViewModel { } </code></pre> <p>Customer specific control:</p> <pre><code>&lt;UserControl x:Class="SilverlightClassLibrary1.CustomView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"&gt; &lt;Grid x:Name="LayoutRoot" Background="White"&gt; &lt;RadioButton x:Name="Test" Content="{Binding Path=Test}"/&gt; &lt;/Grid&gt; &lt;/UserControl&gt; [Export(typeof(IMyViewModel))] [ExportMetadata("Name", "Plugind")] [ExportMetadata("Priority", 2)] public class CustomViewModel : MainControlViewModel, IHarnessAware, IMyViewModel { } </code></pre> <p>Export interface:</p> <pre><code>public interface IMyViewModel { } </code></pre> <p>ExportMetadata interface:</p> <pre><code> public interface IPluginMetadata { string Name { get; } [DefaultValue(0)] int Priority { get; } } </code></pre> <p><strong>I did use this to answer the question, because I am still interested in input from other people who may have already solved a simlilar problem.</strong></p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload