EF / Silverlight应用程序的项目结构 [英] Project structure for EF/Silverlight application

查看:114
本文介绍了EF / Silverlight应用程序的项目结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在为3层解决方案寻找一个很好的项目结构,以避免在一个新项目中出现不必要的工作。



该项目将包含一个核心具有




  • 的模型项目,其中包含具有业务的EF代码第一模型

  • 项目客户端上的

  • 存储库项目中的逻辑和通信逻辑

  • 具有视图和视图模型的silverlight项目(想要使用caliburn.micro这里)



现在的问题是,客户可能会有一些特殊要求,可能导致上述所有项目的变化。所以我的想法是,我可以使用基础结构,并为客户创建相同的结构。如果没有任何变化,我只会有空类,只需扩展基类,并且不添加任何内容。



其中带来以下问题:




  • 在实体框架(代码优先)中,在一个项目中已经有基类(已经完全正常运行)是一个问题,并有另一个可能扩展模型的项目有新字段的课程?

  • XAML中更改用户控件是否存在问题?例如,如果我的用户控件由我的核心中的五个文本框组成,并且我想将第二个框更改为单选按钮,但没有其他。



如果有更好的方式处理客户特定的变更,我也会接受对项目结构的更改。



编辑:我会可能使用以下方法来解决问题。



实体框架



代码首先,似乎有可能有一个模型项目扩展另一个项目。这意味着我可以写下如下:

  public class CoreAddress {
[Key]
public int AdrId {得到; set;}
public string Street {get; set;}
}

public class CustomerAddress:CoreAddress {
public string StreetNumber {get; set;}
}

只有这样才能使这项工作成为一个必需品DbContext内的行:

 (这作为IObjectContextAdapter).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(<来自其他程序集的实体> )。部件); 

XAML



要在XAML中得到类似的行为,我不得不使用Caliburn.Micro(与MEF结合使用),这是一个很好的帮助。



我将创建UserControls通过使用MEF动态获取的ContentControl元素。这意味着我再次拥有一个包含所有视图和ViewModel的核心项目。如果我需要在某个地方为客户交换一个特殊的控件,我将控件更改为一个ContentControl,并为它创建一个核心视图和ViewModel(与更改请求之前相同)。
ContentControl的此ViewModel使用导出接口和ExportMetadata进行注释,以将优先级设置为1.
现在,我创建另一个具有另一个UserControl的项目,该对象具有一些其他控件而不是核心控件,并再次注释作为具有相同界面的导出,但将我的优先级设置得更高,因此客户特定的控件被加载。



简单的例子:



主用户控件和查看模型:

 < 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 =300d:DesignWidth =400>

< Grid x:Name =LayoutRootBackground =White>
< StackPanel>
< ContentControl x:Name =Item/>
< TextBox x:Name =TextItemText =asdf/>
< / StackPanel>

< / Grid>
< / UserControl>

public class TestViewModel:Screen
{
private object viewModel;
private Lazy< IMyViewModel,IPluginMetadata> [] _orderEditorFactory;

[ImportMany(typeof(IMyViewModel),AllowRecomposition = true)]
public Lazy< IMyViewModel,IPluginMetadata> [] OrderEditorFactory
{
get {return _orderEditorFactory; }
set
{
_orderEditorFactory = value;
Item = _orderEditorFactory.OrderByDescending(lazy => lazy.Metadata.Priority).First()。Value;

}
}
私有对象_item;

public object Item
{
get {return _item; }
set
{
_item = value;
NotifyOfPropertyChange(()=> Item);
}
}
}

核心控制:

 < 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 =300d:DesignWidth =400>
< StackPanel>
< TextBlock x:Name =TestText =Core控件的文本/>
< / StackPanel>
< / UserControl>

[Export(typeof(IMyViewModel))]
[ExportMetadata(Name,Pluginc)]
[ExportMetadata(Priority,30)]
public class MainControlViewModel:Screen,IHarnessAware,IMyViewModel
{

}

客户具体控制:

 < 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 =300d:DesignWidth =400>

< Grid x:Name =LayoutRootBackground =White>
< RadioButton x:Name =TestContent ={Binding Path = Test}/>
< / Grid>
< / UserControl>

[Export(typeof(IMyViewModel))]
[ExportMetadata(Name,Plugind)]
[ExportMetadata(Priority,2)]
public class CustomViewModel:MainControlViewModel,IHarnessAware,IMyViewModel
{
}

导出界面:

 公共界面IMyViewModel 
{

}

ExportMetadata界面:

  public界面
IPluginMetadata
{
string Name {get; }
[DefaultValue(0)]
int优先级{get; }
}

我使用这个来回答这个问题,因为我仍然对其他可能已经解决了类似问题的人的投入感兴趣。

解决方案

关于项目结构:
您可以创建一个基础项目,并提供所需的所有关注层。模型,业务,视图,存储库等。



还创建一些基本流程,例如,一个视图,其控制器直到存储库。将其保存在您的代码库中,然后在需要创建新项目时将其分叉。



现在,而不是使用时间来设置,您只需要一些时间根据您的项目需要自定义。



关于XAML: IMHO,如果您更改组件,则应确保它返回与您的项目相同的数据类型控制预期。如果您交换一个复选框的文本框,请确保该检查返回一个字符串到控制器。


I am currently working on finding a good project structure for a 3-tier solution to avoid unnecessary work in a new project.

The project will consist of a core product which has

  • model project which holds the EF code first models
  • project which has the business logic and communication logic on the server
  • repository project on the client
  • silverlight project with views and view models (would like to use caliburn.micro here)

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.

Which brings me to the following problems:

  • 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?
  • 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.

I will also accept changes to the project structure, if there is a better way to handle customer specific changes.

Edit: I will probably use the following approach to solve the problem.

Entity Framework:

With code first it seems to be possible to have one model project extend another project. This means I could write something like:

public class CoreAddress{
  [Key]
  public int AdrId{get; set;}
  public string Street {get;set;}
}

public class CustomerAddress : CoreAddress{
  public string StreetNumber {get; set;}
}

Only thing that is needed in order to make that work is a line inside the DbContext:

(this as IObjectContextAdapter).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(<entity from other assembly>).Assembly);

XAML

To get a similar behavior in XAML I had to use Caliburn.Micro (in combination with MEF) which is a great help here.

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.

Short example for this:

Main user control and view model:

<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">

    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel>
            <ContentControl x:Name="Item"/>
            <TextBox x:Name="TextItem" Text="asdf"/>
        </StackPanel>

    </Grid>
</UserControl>

public class TestViewModel : Screen
    {
        private object viewModel;
        private Lazy<IMyViewModel, IPluginMetadata>[] _orderEditorFactory;

        [ImportMany(typeof(IMyViewModel), AllowRecomposition = true)]
        public Lazy<IMyViewModel, IPluginMetadata>[] OrderEditorFactory
        {
            get { return _orderEditorFactory; }
            set
            {
                _orderEditorFactory = value;
                Item = _orderEditorFactory.OrderByDescending(lazy => lazy.Metadata.Priority).First().Value;

            }
        }
    private object _item;

        public object Item
        {
            get { return _item; }
            set
            {
                _item = value;
                NotifyOfPropertyChange(() => Item);
            }
        }
    }

Core Control:

<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">
    <StackPanel>
        <TextBlock x:Name="Test" Text="Text from Core control"/>
    </StackPanel>
</UserControl>

[Export(typeof (IMyViewModel))]
[ExportMetadata("Name", "Pluginc")]
[ExportMetadata("Priority", 30)]
public class MainControlViewModel : Screen, IHarnessAware, IMyViewModel
{

}

Customer specific control:

<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">

    <Grid x:Name="LayoutRoot" Background="White">
        <RadioButton x:Name="Test" Content="{Binding Path=Test}"/>
    </Grid>
</UserControl>

[Export(typeof(IMyViewModel))]
[ExportMetadata("Name", "Plugind")]
[ExportMetadata("Priority", 2)]
public class CustomViewModel : MainControlViewModel, IHarnessAware, IMyViewModel
{
}

Export interface:

public interface IMyViewModel
{

}

ExportMetadata interface:

   public interface 
        IPluginMetadata
    {
        string Name { get; }
        [DefaultValue(0)]
        int Priority { get; }
    }

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.

解决方案

About project structure: You can create a base project, with every concern layer you need. Model, business, views, repositories and so on.

Also create some basic flow, for example, a single view with its controller up to the repository. Save it in your codebase, then fork it whenever you need to create a new project.

Now instead of using time to set up, you'll just need some time to customize as your project require.

About XAML: IMHO, if you change the component, you should be sure it returns the same datatype as your control expects. If you swap a textbox for a checkbox, be sure the check returns a string to the controller.

这篇关于EF / Silverlight应用程序的项目结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆