public void Generate()
        {
            if (Context.Language == CodeLanguage.VB)
            {
                // turn option strict on for VB if in project settings

                VSProject project = (VSProject) Context.ProjectItem.ContainingProject.Object;
                Property prop = project.Project.Properties.Item("OptionExplicit");

                if ((prjOptionStrict) prop.Value == prjOptionStrict.prjOptionStrictOn)
                {
                    Context.CompileUnit.UserData.Add("AllowLateBound", false);
                }
            }

            CodeNamespace nameSpace = new CodeNamespace(Context.Namespace);
            nameSpace.Imports.AddRange(Context.Model.NamespaceImports.ToArray());
            Context.CompileUnit.Namespaces.Add(nameSpace);

            TemplateMemberGenerator templateMemberGenerator = new TemplateMemberGenerator(Context);
            templateMemberGenerator.AddTemplateUsings();

            foreach (ModelClass cls in Context.Model.Classes)
            {
                GenerateClass(cls, nameSpace, templateMemberGenerator);
            }

            foreach (NestedClass cls in Context.Model.NestedClasses)
            {
                GenerateNestedClass(cls, nameSpace);
            }

            if (Context.Model.GenerateMetaData != MetaDataGeneration.False)
            {
                GenerateMetaData(nameSpace);
            }

            GenerateInternalPropertyAccessor(Context, Context.Model, nameSpace);

            GenerateHelperClass(nameSpace);

            if (Context.Model.Target == CodeGenerationTarget.ActiveRecord)
            {
                Context.PrimaryOutput = GenerateCode(Context.CompileUnit);

                if (Context.Model.UseNHQG)
                {
                    try
                    {
                        AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
                        Assembly assembly = GenerateARAssembly(Context.CompileUnit, false);
                        UseNHQG(assembly);
                    }
                    finally
                    {
                        AppDomain.CurrentDomain.AssemblyResolve -= AssemblyResolve;
                    }
                }
            }
            else
            {
                Type starter = null;
                Assembly assembly = null;

                AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolve);
                try
                {
                    _activeRecord = Assembly.Load(Context.Model.ActiveRecordAssemblyName);

                    // Code below means: ActiveRecordStarter.ModelsCreated += new ModelsCreatedDelegate(OnARModelCreated);
                    starter = _activeRecord.GetType("Castle.ActiveRecord.ActiveRecordStarter");
                    EventInfo eventInfo = starter.GetEvent("ModelsValidated");
                    if (eventInfo == null)
                    {
                        eventInfo = starter.GetEvent("ModelsCreated");
                    }
                    Type eventType = eventInfo.EventHandlerType;
                    MethodInfo info =
                        GetType().GetMethod("OnARModelCreated", BindingFlags.Public | BindingFlags.Instance);
                    Delegate del = Delegate.CreateDelegate(eventType, this, info);
                    eventInfo.AddEventHandler(this, del);

                    assembly = GenerateARAssembly(Context.CompileUnit, !Context.Model.UseNHQG);
                }
                finally
                {
                    AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(AssemblyResolve);
                }

                // Code below means: ActiveRecordStarter.Initialize(assembly, new InPlaceConfigurationSource());
                Type config = _activeRecord.GetType("Castle.ActiveRecord.Framework.Config.InPlaceConfigurationSource");
                object configSource = Activator.CreateInstance(config);
                try
                {
                    starter.InvokeMember("ResetInitializationFlag",
                                         BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, null);
                    starter.InvokeMember("Initialize",
                                         BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null,
                                         null,
                                         new object[] { assembly, configSource });
                }
                catch (TargetInvocationException ex)
                {
                    // Eat config errors
                    if (!ex.InnerException.Message.StartsWith("Could not find configuration for"))
                        throw;
                }
                ClearARAttributes(Context.CompileUnit);
                Context.PrimaryOutput = GenerateCode(Context.CompileUnit);

                foreach (KeyValuePair<string, string> pair in _nHibernateConfigs)
                {
                    string path = Path.Combine(Context.ModelFilePath, RemoveNamespaceFromStart(pair.Key) + ".hbm.xml");
                    using (StreamWriter writer = new StreamWriter(path, false, Encoding.Unicode))
                    {
                        writer.Write(pair.Value);
                    }

                    AddToProject(path, prjBuildAction.prjBuildActionEmbeddedResource);
                }

                if (Context.Model.UseNHQG)
                {
                   UseNHQG(assembly);
                }
            }
        }
        private CodeTypeDeclaration GenerateClass(ModelClass cls, CodeNamespace nameSpace, TemplateMemberGenerator templateMemberGenerator)
        {
            if (cls == null)
                throw new ArgumentNullException("cls", "Class not supplied");
            if (nameSpace == null)
                throw new ArgumentNullException("nameSpace", "Namespace not supplied");
            if (String.IsNullOrEmpty(cls.Name))
                throw new ArgumentException("Class name cannot be blank", "cls");

            CodeTypeDeclaration classDeclaration = GetClassDeclaration(cls, nameSpace);

            GenerateCommonPrimaryKey(cls, classDeclaration);

            List<ModelProperty> compositeKeys = new List<ModelProperty>();

            // Properties and Fields
            foreach (ModelProperty property in cls.Properties)
            {
                PropertyData propertyData = new PropertyData(property);

                if (property.KeyType != KeyType.CompositeKey)
                {
                    AddMemberField(classDeclaration, propertyData);

                    if (property.DebuggerDisplay)
                        classDeclaration.CustomAttributes.Add(propertyData.GetDebuggerDisplayAttribute());
                    if (property.DefaultMember)
                        classDeclaration.CustomAttributes.Add(propertyData.GetDefaultMemberAttribute());
                }
                else
                    compositeKeys.Add(property);
            }

            if (compositeKeys.Count > 0)
            {
                CodeTypeDeclaration compositeClass =
                    GetCompositeClassDeclaration(nameSpace, classDeclaration, compositeKeys, cls.DoesImplementINotifyPropertyChanged());

                // TODO: All access fields in a composite group assumed to be the same.
                // We have a model validator for this case but the user may save anyway.
                // Check if all access fields are the same.
                CodeMemberField memberField = GetPrivateMemberFieldOfCompositeClass(compositeClass, PropertyAccess.Property);
                classDeclaration.Members.Add(memberField);

                classDeclaration.Members.Add(GetActiveRecordMemberCompositeKeyProperty(compositeClass, memberField, cls.DoesImplementINotifyPropertyChanged(), cls.DoesImplementINotifyPropertyChanging()));
            }

            //ManyToOne links where this class is the target (1-n)
            ReadOnlyCollection<ManyToOneRelation> manyToOneSources = ManyToOneRelation.GetLinksToSources(cls);
            foreach (ManyToOneRelation relationship in manyToOneSources)
            {
                GenerateHasManyRelation(classDeclaration, nameSpace, relationship);
            }

            //ManyToOne links where this class is the source (n-1)
            ReadOnlyCollection<ManyToOneRelation> manyToOneTargets = ManyToOneRelation.GetLinksToTargets(cls);
            foreach (ManyToOneRelation relationship in manyToOneTargets)
            {
                GenerateBelongsToRelation(classDeclaration, nameSpace, relationship);
            }

            //ManyToMany links where this class is the source
            ReadOnlyCollection<ManyToManyRelation> manyToManyTargets = ManyToManyRelation.GetLinksToManyToManyTargets(cls);
            foreach (ManyToManyRelation relationship in manyToManyTargets)
            {
                GenerateHasAndBelongsToRelationFromTargets(classDeclaration, nameSpace, relationship);
            }

            //ManyToMany links where this class is the target
            ReadOnlyCollection<ManyToManyRelation> manyToManySources = ManyToManyRelation.GetLinksToManyToManySources(cls);
            foreach (ManyToManyRelation relationship in manyToManySources)
            {
                GenerateHasAndBelongsToRelationFromSources(classDeclaration, nameSpace, relationship);
            }

            //OneToOne link where this class is the source
            OneToOneRelation oneToOneTarget = OneToOneRelation.GetLinkToOneToOneTarget(cls);
            if (oneToOneTarget != null)
            {
                GenerateOneToOneRelationFromTarget(classDeclaration, nameSpace, oneToOneTarget);
            }

            //OneToOne links where this class is the target
            ReadOnlyCollection<OneToOneRelation> oneToOneSources = OneToOneRelation.GetLinksToOneToOneSources(cls);
            foreach (OneToOneRelation relationship in oneToOneSources)
            {
                GenerateOneToOneRelationFromSources(classDeclaration, nameSpace, relationship);
            }

            //Nested links
            ReadOnlyCollection<NestedClassReferencesModelClasses> nestingTargets =
                NestedClassReferencesModelClasses.GetLinksToNestedClasses(cls);
            foreach (NestedClassReferencesModelClasses relationship in nestingTargets)
            {
                GenerateNestingRelationFromRelationship(classDeclaration, relationship);
            }

            // TODO: Other relation types (any etc)

            GenerateDerivedClass(cls, nameSpace);

            templateMemberGenerator.AddTemplateMembers(cls, classDeclaration);

            return classDeclaration;
        }