首页 > 代码库 > Naked objects 起步
Naked objects 起步
If you’re new to Naked Objects start by trying this ultra-simple example: Writing your first Naked Objects application. Then you can progress in a slightly more formal manner.
A Naked Objects application will typically consist of multiple projects.
First, there will typically be one or more ‘Model’ projects, containing your domain classes. See:
Creating a domain model project
Next you will need one or more ‘Run’ projects. If you want a ready-made user interface then you should add an MVC project. See:
Running your domain model(s) as a Naked Objects MVC application
Later you might also decide to add a Restful API, as an alternative way to ‘run’ your domain model:
Creating and using a Restful Objects API
Or the ability to run as a standalone executable, for example for Batch operations:
Running without a user interface
You will also want to add one or more ‘Test’ projects. These may be conventional Unit Tests, but we strongly recommend that you also consider using the powerful Naked Objects XAT framework, to write functional or integration tests that are UI-independent:
Executable Application Tests (XATs)
If you are sticking to the generic Naked Objects MVC User Interface then there is typically no need to then write UI tests (which are notoriously brittle to change). But if you customise the user interface (other than just by modifying the CSS) then you should write UI tests. We’ve written some helper classes to work with the respected Selenium framework, see:
End to End Testing with Selenium
Writing your first Naked Objects application
Follow these steps to write your first ultra-simple Naked Objects application, featuring one simple domain class only:
- Using Visual Studio 2013 (Express version is fine) create a new ASP.NET Web Application project called, say, MyWebApp, using the MVC template.
- Install the NuGet Package NakedObjects.Mvc-FileTemplates, selecting Yes To All when asked if you wish to overwrite existing files.
- In the Models folder add a new class Customer as follows. Note that:
- All properties in a Naked Objects application must be virtual.
- [Hidden] specifies that this property is not for display on the user interface.
- [Title] specifes that the value of the property should be displayed in the Tab.
using NakedObjects;
namespace MyWebApp
{
public class Customer
{
[Hidden]
public virtual int Id { get; set; }
[Title]
public virtual string Name { get; set; }
}
}
- Create a DbContext object as follows. (This is standard Entity Framework Code First coding.)
using System.Data.Entity;
namespace MyWebApp
{
public class MyDbContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
}
}
- In the App_Start folder find the RunWeb class and edit two members as follows. First, the MenuServices property which defines the services to be shown on the main menu. (NakedObjects.Services.SimpleRepository is a ready-made class for early-stage prototyping only.)
protected override IServicesInstaller MenuServices {
get {
return new ServicesInstaller(
new SimpleRepository<Customer>());
}
}
Second, the Persistor property, in which we need to specify the DbContext(s) that it needs to inspect:
protected override IObjectPersistorInstaller Persistor
{
get
{
var installer = new EntityPersistorInstaller();
installer.UsingCodeFirstContext(() => new MyDbContext());
return installer;
}
}
- Run the project. Using the actions on the Customers menu, try creating and retrieving Customer objects.
Creating a domain model project
Naked Objects uses Microsoft’s Entity Framework to persist domain objects in a database. Most developers who work with Entity Framework now use it in ‘Code First’ mode - and this is what we now use throughout this manual. The name is slightly misleading: you can use ‘Code First’ mode even when creating an application to work against an existing database – ‘Code First’ just means that your persistence is entirely defined in program code (typically C#). Naked Objects can, however, work equally well with Entity Franework in the older mode, where the entity model is defined in XML with a .edmx file.
This manual does not attempt to provide an introduction to Entity Framework Code First development - rather it just emphasises what you need to do to make your project work with Naked Objects. We therefore recommend that you gain some general familiarity with Entity Framework Code First development: there are numerous on-line tutorials, and we also strongly recommend the book Programming Entity Framework - Code First by Julia Lerman and Rowan Millar.
When copying any domain code examples from the book or on-line Code First tutorials mentioned, please remember the following basic rules:
- Naked Objects requires that all properties are virtual.
- Naked Objects requires that all collections are virtual, and are initialised (but not in a constructor). See Collection properties.
- Entity Framework Code First makes all properties optional in the database, unless specified as mandatory (using the Required attribute, or via the Code First Fluent API). However, at the user interface (in Naked Objects MVC) or Restful API (Restful Objects for .NET) the Naked Objects framework treats all properties as mandatory, unless marked up with the Optionally attribute - as we believe that this is the safer default behaviour. Note that it is possible to configure Naked Objects to work the other way if you wish (see Optional vs. Required).
Define your model project(s)
Your starting point will be to develop one or more Model projects, as follows:
- Create a new Class Library project.
- Invoke Manage NuGet Packages, find and install the
NakedObjects.ProgrammingModel
package (see also note below about Naked Objects IDE) - Add POCO domain classes, following the simple programming conventions that are recognised by the Naked Objects framework. See Domain object.
- Create some services to act as Repositories/Factories.
Naked Objects IDE
When you installed the NakedObjects.ProgrammingModel via the NuGet Package Manager, it automatically added the NakedObjects.Ide package, which consists of a set of Item Templates and Code Snippets that can be very useful when construction your domain model. The item templates are used when invoking Add > New Item: you will find them listed under Naked Objects for the C# programming language. To see the list of code snippets: Tools > Code Snippets Manager > [Language] > My Code Snippets > Naked Objects. Most can be invoked using their shortcut, such as ‘propcho‘ to add a Choices method for a property. Note, however, that if you have other tools installed, such as Resharper, then these can sometimes invalidate the shortcuts. The IDE has been placed in its own package so that you have the option when un-installing the NakedObjects.ProgrammingModel from a specific project, whether or not you want to uninstall the IDE, which may be used by multiple projects.
Define your DbContext(s)
Next you will need to set up a ‘Context‘ class for your model project, which is defined in exactly the same way as for conventional Code First development. You can use the Naked Objects > DbContext item template to help create this class - as shown in the example below:
namespace DataAccess
{
public class MyContext : DbContext
{
public MyContext(string name) : base(name) { }
public MyContext() { }
public DbSet<Foo> Foos { get; set; }
public DbSet<Bar> Bars { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Initialisation
//Use the Naked Objects > DbInitialiser template to add a custom initialiser, then reference thus:
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());
//Mappings
//Use the Naked Objects > Mapping template to add mapping classes & reference them thus:
//modelBuilder.Configurations.Add(new Employee_Mapping());
}
}
}
The context inherits from the class System.Data.Entity.DbContext
it defines methods to return one or more DbSet
s.
It is not necessary to define a DbSet
for each of your domain classes - just for the ‘root‘ classes in your model hierarchy.
Within the OnModelCreating
method you may also:
- Add database mappings using the Code First ‘Fluent API‘. Use the Naked Objects > DbMapping item template to create a mapping class quickly.
- Add a database initialiser to determine when/whether to drop and re-create the schema. Use the Naked Objects > DbInitialiser item template to create an initialiser class quickly. You can use this initializer to seed the database, but you should consider - as an alternative - using Naked Objects‘ own Data Fixtures pattern as this has several advantages,
Overriding the default database schema generation
By default, Entity Framework Code First creates the database schema by following a set of conventions, based on the class and property names. These convention-based schema may be over-ridden or enhanced, either by using Code First Data Annotations in the domain classes, or by means of the Code First Fluent API. The latter is invoked by creating one or more configuration classes (inheriting from EntityTypeConfiguration<T>
) and referencing them from within the DbContext
, as in the following example (quoted from Programming Entity Framework - Code First by Julia Lerman and Rowan Millar):
namespace DataAccessFluent
{
public class DestinationConfiguration : EntityTypeConfiguration<Destination>
{
public DestinationConfiguration()
{
Property(d => d.Name).IsRequired();
Property(d => d.Description).HasMaxLength(500);
Property(d => d.Photo).HasColumnType("image");
}
}
namespace DataAccessFluent
{
public class DestinationConfiguration : EntityTypeConfiguration<Destination>
{
public DestinationConfiguration()
{
Property(d => d.Name).IsRequired();
Property(d => d.Description).HasMaxLength(500);
Property(d => d.Photo).HasColumnType("image");
}
}
public class LodgingConfiguration : EntityTypeConfiguration<Lodging>
{
public LodgingConfiguration()
{
Property(l => l.Name).IsRequired().HasMaxLength(200);
Property(l => l.Owner).IsUnicode(false);
Property(l => l.MilesFromNearestAirport).HasPrecision(8, 1);
}
}
//...
public class BreakAwayContextFluent : DbContext
{
public BreakAwayContextFluent(string name) : base(name) { }
public BreakAwayContextFluent() { }
public DbSet<Destination> Destinations { get; set; }
public DbSet<Lodging> Lodgings { get; set; }
//...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new DestinationConfiguration());
modelBuilder.Configurations.Add(new LodgingConfiguration());
// ...
}
}
}
Using data fixtures with Code First
When working Code First, one option for creating data fixtures (to pre-populate the database with) is via the Seed
method on the Database Initializer. The following example is quoted from Programming Entity Framework - Code First by Julia Lerman and Rowan Millar):
namespace DataAccess
{
public class DropCreateBreakAwayWithSeedData : DropCreateDatabaseAlways<BreakAwayContext>
{
protected override void Seed(BreakAwayContext context)
{
context.Destinations.Add(new Model.Destination {
Name = "Great Barrier Reef" });
context.Destinations.Add(new Model.Destination { Name = "GrandCanyon"});
//...
}
}
}
This custom database initializer may be set within the Persistor
property of the Run class, as described earlier in this section, or within the OnModelCreating()
method on your DbContext
.
Another option is to use Naked Objects‘ own Data Fixturespattern, which has the advantage that you can delegate to methods on servicesand objects just as if they were created by the user.
Running yourdomain model(s) as a Naked Objects MVC application
Follow these steps to run your domain model(s) with theNaked Objects MVC user interface.
- Create a new C# ASP.NET WebApplication project, specifying MVC as the template,and set this as the StartupProject for your solution.
- Invoke ManageNuget Packages, find and install the
NakedObjects.Mvc-FileTemplates
package into this project - Add project reference(s) toyour Model project(s).
- Copy the connection string(s)from the
App.config
file(s) in your Model project(s) into theWeb.config
in your Run project.
There are two web.config
files in a standard MVC project - one within the Views folder (the purpose ofwhich is to prevent direct access to the views without going through acontroller) and the other at the project root level. The connection stringneeds to go into the latter.
- Open the
RunWeb
class(within theApp_Start
folder). Within this Run class, register your services, fixtures (ifrequired), and make any other changes you may require to the default runconfiguration. - Run the project as a local app.This will launch a web-browser pointing at the start page of your application,running within
LocalHost
. - Even if you selected the Internetproject template, by default, the application is not initially set up torequire a log-on. When you are ready to add authorization to your prototype,simply un-comment the commented-out the
[Authorize]
attributeon theGenericController
andSystemController
classes. - When you are ready, you candeploy the application to a server running IIS, in exactly the same way as anyother ASP.NET MVC application. The simplest way is to right-click on theproject and invoke the Publish action.
Naked objects 起步