Sei sulla pagina 1di 36

11/6/2015 Creating class extensions

Creating class extensions

Summary
A  class  extension  allows  custom  behavior  to  be  applied  to  object  classes  and  feature  classes  in  a  geodatabase.  Typically,  a
class  extension  is  used  for  tasks,  such  as  implementing  validation  rules  that  are  not  possible  out­of­the­box,  custom
rendering  in  a  map,  and  listening  for  class  events.  Class  extensions  are  the  most  important  type  of  geodatabase
customization. 

This  topic  explains  what  class  extensions  are  typically  used  for  and  how  to  perform  each  step  in  creating  a  class  extension,
from  its  initial  creation  in  Visual  Studio  through  implementation,  component  category  registration,  and  application  to  a  new
or  existing  object  class.  It  also  explains  how  to  implement  each  class  extension  interface  (required  and  optional),  create
custom  description  classes,  and  effectively  manage  and  use  extension  properties. 

In this topic
Common  uses  of  class  extensions
Creating  a  class  extension
Applying  a  class  extension
Implementing  interfaces
IClassExtension
Working  with  extension  properties
IObjectClassExtension  and  IFeatureClassExtension
IObjectClassEvents
IObjectClassValidation
IObjectClassInfo  and  IObjectClassInfo2
IRelatedObjectClassEvents  and  IRelatedObjectClassEvents2
IConfirmSendRelatedObjectEvents
IObjectInspector
IFeatureClassEdit
IFeatureClassDraw
Creating  custom  class  descriptions

Common uses of class extensions
Use  class  extensions  to  customize  geodatabase  behavior  that  applies  to  a  single  object  class  or  feature  class.  The  following
includes  examples  of  functionality  that  can  be  implemented  with  class  extensions:
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 1/36
11/6/2015 Creating class extensions

Handling  events  triggered  by  object  creation,  deletion,  or  modification—The  IObjectClassEvents interface  can  be
implemented  to  obtain  this  functionality.
Validation  rules  too  specific  or  complex  to  be  applied  out­of­the­box—The  IObjectClassValidation interface  allows
extensions  to  customize  the  validation  process.
 Handling  events  from  related  datasets—The  following  interfaces  can  be  used,  depending  on  the  requirements  of  the
class  extension:  IRelatedObjectClassEvents,  IRelatedObjectClassEvents2,  and  IConfirmSendRelatedObjectEvents.
Defining  custom  split  policies  for  relationship  classes—The  IFeatureClassEdit interface  can  be  used  and  despite  its
name,  it  can  be  used  with  feature  or  object  class  extensions.
Specifying  custom  renderers  for  feature  classes—The  IFeatureClassDraw interface  can  be  implemented  to  associate  a
custom  renderer  with  a  feature  class,  with  the  option  of  making  it  the  exclusive  renderer  for  the  class.
Storage  of  data  associated  with  the  class,  such  as  text,  numbers,  or  objects—This  data  can  be  stored  in  member
variables  and  used  by  public  and  private  extension  members.  These  key­value  pairs  are  referred  to  as  class  extension
properties.
Methods  and  properties  defined  by  a  custom  interface  (or  no  interface)  can  be  implemented  by  a  class
extension—This  is  a  useful  place  to  define  properties  to  access  and  modify  extension  properties  or  to  implement  methods
for  extension  specific  behavior.
 

Creating a class extension
When  creating  a  class  extension,  the  following  attributes  and  methods  are  required  (or  recommended)  for  the  extension  to
function  properly:
 Three  attributes  from  the  System.Runtime.InteropServices  namespace:  globally  unique  identifier  (GUID),  ClassInterface,
and  ProgID
Component  Object  Model  (COM)  register  and  unregister  methods,  which  call  ArcGIS  component  category  registration  and
unregistration  methods
 
The  following  code  example  shows  the  attributes:
 
[C#]
[Guid("a78421ba‐0d38‐4104‐be58‐b049b16f637c")][ClassInterface
       (ClassInterfaceType.None)][ProgId("SampleClassExt.SampleClassExtension")
       ][ComVisible(true)]
public  class  SampleClassExtension:  IClassExtension,  IObjectClassExtension
{
       //  Class  members  here…
}

[VB.NET]
<Guid("a78421ba‐0d38‐4104‐be58‐b049b16f637c"),  _

           ClassInterface(ClassInterfaceType.None),  _
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 2/36
11/6/2015 Creating class extensions
           ClassInterface(ClassInterfaceType.None),  _
           ProgId("ClassExtensionArticle.SampleClassExtension"),  _
           ComVisible(True)>  _
           Public  Class  SampleClassExtension
       Implements  IClassExtension,  IObjectClassExtension
      
       '  Class  members  here…
      
End  Class

The  GUID's  attribute  parameter  should  be  randomly  generated  by  Visual  Studio  or  another  application.  The  ProgID's  attribute
parameter  should  be  the  fully  qualified  name  of  the  class.  Copying  and  pasting  the  values  in  the  preceding  code  example  without
modification  is  not  recommended.
The  following  code  example  shows  the  COM  register  and  unregister  methods:
 
[C#]
[ComRegisterFunction()][ComVisible(false)]  static  void  RegisterFunction(Type
       registerType)
{
       string  regKey  =  string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}",
               registerType.GUID);
       GeoObjectClassExtensions.Register(regKey);
}

[ComUnregisterFunction()][ComVisible(false)]  static  void  UnregisterFunction(Type


       registerType)
{
       string  regKey  =  string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}",
               registerType.GUID);
       GeoObjectClassExtensions.Unregister(regKey);
}

[VB.NET]
<ComRegisterFunction(),  ComVisible(False)>  _
                                         Shared  Sub  RegisterFunction(ByVal  registerType  As  Type)
       Dim  regKey  As  String  =  String.Format("HKEY_CLASSES_ROOT\CLSID\{{{0}}}",  registerType.GUID)
       GeoObjectClassExtensions.Register(regKey)
End  Sub

<ComUnregisterFunction(),  ComVisible(False)>  _
                                             Shared  Sub  UnregisterFunction(ByVal  registerType  As  Type)
       Dim  regKey  As  String  =  String.Format("HKEY_CLASSES_ROOT\CLSID\{{{0}}}",  registerType.GUID)
       GeoObjectClassExtensions.Unregister(regKey)
End  Sub

Although  it  is  possible  to  manually  add  these  methods,  ArcGIS  and  Visual  Studio  provide  the  functionality  for  a  class  extension
to  be  generated  automatically.  See  the  following  steps:
1.  On  the  Solution  Explorer,  right­click  the  project  that  contains  the  class  extension,  click  Add,  then  click  New  Item.
The  Add  New  Item  dialog  box  appears.  See  the  following  screen  shot: 

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 3/36
11/6/2015 Creating class extensions

2.   On  the  Add  New  Item  dialog  box,  click  ArcGIS  under  the  Categories  pane  and  click  ArcGIS  Class  under  the  Templates
pane.  Type  an  appropriate  name  for  the  class  extension  in  the  Name  text  box  and  click  Add.  The  ArcGIS  Add  Class
Wizard  dialog  box  appears.  See  the  following  screen  shot:

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 4/36
11/6/2015 Creating class extensions

3.  On  the  ArcGIS  Add  Class  Wizard,  under  Customization  Group,  click  the  first  drop­down  arrow  and  choose  All,  then
choose  Geodatabase  from  the  second  drop­down  arrow.  Click  Class  Extension  under  Base  Component  and  click  Next.
The  ESRI  GeoObject  Class  Extensions  component  category  appears.  See  the  following  screen  shot:

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 5/36
11/6/2015 Creating class extensions

 
4.  Select  the  ESRI  GeoObject  Class  Extensions  check  box  and  click  Next.  A   list  of  available  optional  interfaces  appear,
which  is  only  a  subset  of  the  optional  interfaces.  Despite  being  termed  optional,  always  choose  IObjectClassExtension
from  this  list  and  if  the  class  extension  applies  to  feature  classes,  also  choose  IFeatureClassExtension.  Choose  any
other  interfaces  to  implement  and  click  Finish.  See  the  following  screen  shot:

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 6/36
11/6/2015 Creating class extensions

Create  a  class  extension  in  a  class  library  that  is  registered  for  COM  interop.  To  ensure  a  class  library  is  registered  for  COM
interop,  in  Visual  Studio  right­click  the  project  and  click  Properties.  Select  the  COM  interop  check  box  near  the  bottom  of  the
Build  page.

Applying a class extension
There  are  several  ways  to  apply  an  extension  to  a  class,  depending  on  whether  the  class  already  exists  and  whether  the
extension  is  applied  through  an  application  or  programmatically.  Two  options  exist  to  apply  an  extension  to  new  object  classes—
creating  description  classes  and  passing  the  class  extension's  GUID  as  a  parameter  of  the  IFeatureWorkspace.CreateTable and
CreateFeatureClass methods.  For  existing  object  classes,  class  extensions  can  be  applied  through  the  IClassSchemaEdit and
IFeatureWorkspaceSchemaEdit interfaces.
Classes  can  have  a  maximum  of  one  associated  extension.
Creating  and  registering  description  classes  for  an  extension  has  the  benefit  of  allowing  ArcCatalog  to  "find"  the  new  class
extension  and  letting  users  create  classes  with  the  extension  through  that  application.  For  more  information  on  creating
description  classes,  see  Creating  custom  class  descriptions  in  this  topic.
 
Passing  the  class  extension's  GUID  to  the  IFeatureWorkspace.CreateTable  or  IFeatureWorkspace.CreateFeatureClass  methods  can
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 7/36
11/6/2015 Creating class extensions

be  quicker  during  testing  and  debugging  of  the  class  extension,  but  in  most  cases,  even  custom  clients  benefit  from  the
implementation  of  an  object  class  description.
 
To  apply  an  extension  to  an  existing  class,  obtain  an  exclusive  schema  lock,  then  call  the
IClassSchemaEdit.AlterClassExtensionCLSID method.  This  method  can  also  be  used  to  remove  a  class  extension  by  providing  null
values  as  both  parameters.  See  the  following  code  example:
 
[C#]
public  void  ChangeClassExtension(IObjectClass  objectClass,  String  extensionUID,
       IPropertySet  extensionProperties)
{
       ISchemaLock  schemaLock  =  (ISchemaLock)objectClass;

       try
       {
               //  Attempt  to  get  an  exclusive  schema  lock.
               schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);

               //  Cast  the  object  class  to  the  IClassSchemaEdit2  interface.


               IClassSchemaEdit2  classSchemaEdit  =  (IClassSchemaEdit2)objectClass;

               if  (!String.IsNullOrEmpty(extensionUID))
               {
                       //  Create  a  unique  identifier  (UID)  object  and  change  the  extension.
                       UID  extUID  =  new  UIDClass();
                       extUID.Value  =  extensionUID;
                       classSchemaEdit.AlterClassExtensionCLSID(extUID,  extensionProperties);
               }
               else
               {
                       //  Clear  the  class  extension.
                       classSchemaEdit.AlterClassExtensionCLSID(null,  null);
               }
       }
       catch  (COMException  comExc)
       {
               throw  new  Exception("Could  not  change  class  extension.",  comExc);
       }
       finally
       {
               schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
       }
}

[VB.NET]
Public  Sub  ChangeClassExtension(ByVal  objectClass  As  IObjectClass,  ByVal  extensionUID  As  String,  ByVal  extensionProperties  As  IPropertySet)
       Dim  schemaLock  As  ISchemaLock  =  CType(objectClass,  ISchemaLock)
       Try
       '  Attempt  to  get  an  exclusive  schema  lock.
       schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock)
      
       '  Cast  the  object  class  to  the  IClassSchemaEdit2  interface.
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 8/36
11/6/2015 Creating class extensions
       '  Cast  the  object  class  to  the  IClassSchemaEdit2  interface.
       Dim  classSchemaEdit  As  IClassSchemaEdit  =  CType(objectClass,  IClassSchemaEdit)
       If  Not  String.IsNullOrEmpty(extensionUID)  Then
               '  Create  a  unique  identifier  (UID)  object  and  change  the  extension.
               Dim  extUID  As  UID  =  New  UIDClass()
               extUID.Value  =  extensionUID
               classSchemaEdit.AlterClassExtensionCLSID(extUID,  extensionProperties)
       Else
               '  Clear  the  class  extension.
               classSchemaEdit.AlterClassExtensionCLSID(Nothing,  Nothing)
       End  If
       Catch  comExc  As  COMException
       Throw  New  Exception("Could  not  change  class  extension.",  comExc)
       Finally
       schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock)
       End  Try
End  Sub

If  an  extension  is  faulty  or  has  not  been  properly  installed  on  the  client  machine,  opening  the  class  might  not  be  possible.  If
this  occurs,  the  workspace  can  be  cast  to  the  IFeatureWorkspaceSchemaEdit  interface  and  the  AlterClassExtensionCLSID method
of  that  interface  can  be  called  to  remove  the  extension.

Implementing interfaces
Class  extensions  should  implement,  at  a  minimum,  two  interfaces—IClassExtension and  IObjectClassExtension.  If  the  extension
is  being  designed  for  feature  classes,  also  implement  the  IFeatureClassExtension interface.  IClassExtension  is  the  only  required
interface,  but  IObjectClassExtension  and  IFeatureClassExtension  are  indicator  interfaces  and  implementing  them  will  not  increase
development  time.
Event  handling  within  a  class  extension  is  slightly  different  from  application­level  event  handlers,  such  as  custom  event
listeners.  Rather  than  explicitly  "wiring"  event  handling  methods  to  the  source  of  the  events,  class  extensions  automatically
receive  events  by  implementing  their  optional  event  interfaces,  such  as  IObjectClassEvents.  Custom  objects  can  also  define
event  handlers  for  this  interface.  For  more  information,  see  Listening  to  object  class  events.
Numerous  optional  interfaces  exist  for  object  class  and  feature  class  extensions,  which  includes  the  following:
IObjectClassValidation
IObjectClassEvents
IObjectClassInfo and  IObjectClassInfo2
IRelatedObjectClassEvents  and  IRelatedObjectClassEvents2
IConfirmSendRelatedObjectEvents
IFeatureClassEdit
IFeatureClassDraw (feature  class  extensions  only)
IFeatureClassCreation (feature  class  extensions  only)
 
Developers  should  also  be  aware  of  the  persistence  provided  by  extension  properties.  Extension  properties  are  key­value  pairs
stored  in  the  geodatabase  and  are  unique  to  each  class,  not  the  extension,  allowing  each  instance  of  the  extension  to  maintain

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 9/36
11/6/2015 Creating class extensions

its  own  properties.  Extension  properties  can  be  read  from  the  geodatabase  with  the  IClass.ExtensionProperties property,  and
written  to  the  geodatabase  using  the  IClassSchemaEdit2.AlterClassExtensionProperties method.  If  the  properties  are  used
frequently  by  the  extension,  they  can  be  stored  as  member  variables  during  extension  initialization—they  are  passed  in  as  a
parameter  of  the  IClassExtension.Init method.  This  approach  minimizes  the  amount  of  serialization  and  geodatabase  round­trips.
 
Finally,  members  not  specified  by  any  interface  (or  by  a  custom  interface)  can  be  created  in  an  extension  as  a  way  of  defining
custom  behavior  and  storing  data.  This  is  a  common  way  of  modifying  extension  properties.  These  members  can  then  be
accessed  by  custom  clients  or  other  ArcGIS  customizations,  such  as  editor  or  workspace  extensions,  custom  commands,  or
custom  property  pages.
 
It  is  important  to  remember  that  a  class  extension  can  be  called  by  any  geodatabase  client,  including  ArcMap,  ArcCatalog,  and
custom  clients.  Because  of  this,  the  extension  should  never  be  responsible  for  output,  as  both  graphical  user  interface  (GUI)
output  or  console  output  will  be  inappropriate  for  some  applications.  Writing  to  the  local  file  system,  while  useful  in  some  cases,
should  be  implemented  carefully,  as  not  all  client  machines  have  a  common  file  structure.

IClassExtension
A  class  extension  must  implement  IClassExtension.  It  defines  two  methods—Init  and  Shutdown—which  are  called  when  the  class
extension  is  initialized  and  disposed  of,  respectively.  Class  extensions  are  initialized  when  their  associated  class  is  opened  or
when  they  are  applied  to  an  existing  class.  Shutdown  is  called  when  their  associated  class  is  disposed  of  or  when  the  extensions
are  removed  from  the  class.
Depending  on  the  client,  Shutdown  might  not  be  called  when  a  class  is  deleted.  This  is  because  Shutdown  is  called  when  the
class  is  freed  from  memory,  which  does  not  necessarily  occur  when  a  class  is  deleted  from  a  geodatabase.  If  this  is  the  case,  it
will  be  called  when  the  client  is  closed.
The  Init  method  provides  references  that  can  be  crucial  for  other  methods  to  operate  correctly.  It  has  two  parameters,  one  of
type  IClassHelper  and  one  of  type  IPropertySet.  The  class  helper  is  an  object  that  provides  a  reference  to  the  extension's
associated  class,  which  many  extensions  require.  It  is  highly  recommended  that  this  reference  be  stored  in  a  member  variable
for  use  by  other  properties  and  methods.  The  property  set  contains  the  extension  properties,  if  any  exist.  If  none  exist,  a  null
value  is  passed  into  the  method.  For  more  information  on  extension  properties,  see  Working  with  extension  properties in  this
topic.
 
The  following  code  example  shows  a  simple  implementation  of  the  Init  method:
 
[C#]
private  IClassHelper  classHelper  =  null;

public  void  Init(IClassHelper  classHelper,  IPropertySet  extensionProperties)


{
       //  Store  the  class  helper  reference.
       this.classHelper  =  classHelper;
}

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 10/36
11/6/2015 Creating class extensions

[VB.NET]
Private  classHelper  As  IClassHelper  =  Nothing
      
       Public  Sub  Init(ByVal  classHelper  As  IClassHelper,  ByVal  extensionProperties  As  IPropertySet)  Implements  IClassExtension.Init
               '  Store  the  class  helper  reference.
               Me.classHelper  =  classHelper
       End  Sub

Working with extension properties
Extension  properties  allow  a  set  of  objects  to  be  persisted  with  a  class  as  metadata.  These  properties  can  include  strings,
images,  and  other  objects.  Extension  properties  are  stored  on  a  class­by­class  basis,  not  for  the  extension  as  a  whole,  allowing
each  class  with  the  extension  to  be  configured  individually.
Extension  properties  are  accessible  from  the  extension's  associated  class,  through  the  IClass.ExtensionProperties  property,  and
are  passed  to  the  IClassExtension.Init  method  as  a  parameter.  If  the  properties  are  to  be  used  by  other  methods  within  the
extension,  save  the  properties  in  member  variables  during  the  Init  method.  Properties  can  be  modified  at  any  time  by  casting
the  class  to  the  IClassSchemaEdit2 interface  and  calling  the  AlterClassExtensionProperties  method  with  a  new  set  of  properties
as  a  parameter.  If  the  properties  are  to  be  modified  by  the  extension,  a  reference  to  the  class  can  be  obtained  through  the
extension's  class  helper,  which  is  also  passed  into  the  IClassExtension.Init  method  as  a  parameter.  As  with  other  methods  in  the
IClassSchemaEdit  interfaces,  obtain  an  exclusive  schema  lock  for  the  class  before  modifying  its  extension  properties.
When  a  class  with  an  extension  is  created,  it  has  no  extension  properties  and  the  value  passed  into  the  IClassExtension.Init
parameter  is  null.  If  properties  are  required  for  the  extension  to  operate  correctly,  the  Init  method  can  check  whether  the
incoming  property  set  is  null  and  if  so,  apply  a  default  set  of  properties.
The  following  code  example  shows  an  excerpt  from  an  extension  that  keeps  a  log  file  of  class  activity,  by  using  a  default
location  unless  a  property  is  set  to  override  the  default.  The  LogFile  property  is  a  member  of  a  custom  interface,  accessible  by
a  property  page.
[C#]
private  IPropertySet  extensionProperties  =  null;
private  IClassHelper  classHelper  =  null;

private  const  String  LOGFILE_PROPERTY  =  "LogFile";


private  const  String  DEFAULT_LOGFILE  =  @"C:\Temp\LogFile.txt";

public  void  Init(IClassHelper  classHelper,  IPropertySet  initExtensionProperties)


{
       //  Store  the  class  helper  reference.
       this.classHelper  =  classHelper;

       //  Store  the  extension  properties.


       extensionProperties  =  initExtensionProperties;

       //  Create  extension  properties  if  none  exist.


       if  (extensionProperties  ==  null)
       {
               extensionProperties  =  new  PropertySetClass();
               extensionProperties.SetProperty(LOGFILE_PROPERTY,  DEFAULT_LOGFILE);
       }

}
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 11/36
11/6/2015 Creating class extensions
}

public  String  LogFile


{
       get
       {
               return  extensionProperties.GetProperty(LOGFILE_PROPERTY)as  String;
       }

       set
       {
               //  Get  the  base  class  and  cast  to  the  IClassSchemaEdit2  interface.
               IClass  baseClass  =  classHelper.Class;
               IClassSchemaEdit2  classSchemaEdit  =  (IClassSchemaEdit2)baseClass;

               //  Attempt  to  acquire  an  exclusive  schema  lock.


               ISchemaLock  schemaLock  =  (ISchemaLock)baseClass;
               try
               {
                       schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);

                       //  Set  the  extension  property  and  save  it.


                       extensionProperties.SetProperty(LOGFILE_PROPERTY,  value);
                       classSchemaEdit.AlterClassExtensionProperties(extensionProperties);
               }
               catch  (COMException  comExc)
               {
                       throw  new  Exception(String.Format(
                               "Error  updating  extension  properties:  {0}",  comExc.Message),  comExc);
               }
               finally
               {
                       schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
               }
       }
}

[VB.NET]
Private  extensionProperties  As  IPropertySet  =  Nothing

Private  classHelper  As  IClassHelper  =  Nothing


      
       Private  Const  LOGFILE_PROPERTY  As  String  =  "LogFile"
       Private  Const  DEFAULT_LOGFILE  As  String  =  "C:\Temp\LogFile.txt"
      
       Public  Sub  Init(ByVal  classHelper  As  IClassHelper,  ByVal  extensionProperties  As  IPropertySet)  Implements  IClassExtension.Init
               '  Store  the  class  helper  reference.
               Me.classHelper  =  classHelper
              
               '  Store  the  extension  properties.
               extensionProperties  =  extensionProperties
              
               '  Create  extension  properties  if  none  exist.
               If  extensionProperties  Is  Nothing  Then
                       extensionProperties  =  New  PropertySetClass()
                       extensionProperties.SetProperty(LOGFILE_PROPERTY,  DEFAULT_LOGFILE)
               End  If
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 12/36
11/6/2015 Creating class extensions
               End  If
       End  Sub
      
       Public  Property  LogFile()  As  String
               Get
               Return  CType(extensionProperties.GetProperty(LOGFILE_PROPERTY),  String)
               End  Get
               Set(ByVal  Value  As  String)
               '  Get  the  base  class  and  cast  to  the  IClassSchemaEdit2  interface.
               Dim  baseClass  As  IClass  =  classHelper.Class
               Dim  classSchemaEdit2  As  IClassSchemaEdit2  =  CType(baseClass,  IClassSchemaEdit2)
              
               '  Attempt  to  acquire  an  exclusive  schema  lock.
               Dim  schemaLock  As  ISchemaLock  =  CType(baseClass,  ISchemaLock)
               Try
               schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock)
              
               '  Set  the  extension  property  and  save  it.
               extensionProperties.SetProperty(LOGFILE_PROPERTY,  Value)
               classSchemaEdit2.AlterClassExtensionProperties(extensionProperties)
               Catch  comExc  As  COMException
               Throw  New  Exception(String.Format("Error  updating  extension  properties:  {0}",  comExc.Message),  comExc)
               Finally
               schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock)
               End  Try
               End  Set
       End  Property

IObjectClassExtension and IFeatureClassExtension
The  IObjectClassExtension  and  IFeatureClassExtension  interfaces  do  not  define  any  methods  or  properties,  but  act  as  indicator
interfaces  (they  are  used  to  identify  the  extension's  type).  It  is  recommended  that  all  class  extensions  implement  the
IObjectClassExtension  interface  and  those  that  have  feature  class  specific  functionality  implement  the  IFeatureClassExtension
interface.

IObjectClassEvents
Use  the  IObjectClassEvents  interface  to  define  custom  behavior  when  objects  are  created,  deleted,  or  modified.  These  events
occur  following  the  IRow.Store or  IRow.Delete methods  and  before  the  notification  of  related  or  external  objects.  Because  the
events  follow  Store  and  Delete  calls,  Store  and  Delete  should  not  be  called  on  the  object  from  the  extension's  implementation.
The  following  code  example  shows  how  to  use  the  OnCreate method  to  time­stamp  new  objects  with  their  creation  date.
Implement  OnDelete and  OnChange even  though  in  this  case,  they  do  not  define  any  functionality.
[C#]
private  static  readonly  String  timestampFieldName  =  "CREATED";

//  Set  position  during  IClassExtension.Init  method  using  IClass.FindField.


private  int  timestampFieldPosition  =    ‐  1;

public  void  OnCreate(IObject  obj)


{
       //  Set  the  time  stamp  field's  value  to  the  current  date  and  time.
       obj.set_Value(timestampFieldPosition,  DateTime.Now);
}
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 13/36
11/6/2015 Creating class extensions
}

public  void  OnDelete(IObject  obj)


{
       //  Do  nothing.
}

public  void  OnChange(IObject  obj)


{
       //  Do  nothing.
}

[VB.NET]
Private  Const  TIMESTAMP_FIELD_NAME  As  String  =  "CREATED"

'  Set  position  during  IClassExtension.Init  method  using  IClass.FindField.


Private  timestampFieldPosition  As  Integer  =  ‐1

Public  Sub  OnCreate(ByVal  obj  As  IObject)  Implements  IObjectClassEvents.OnCreate


       If  timestampFieldPosition  >=  0  Then
               obj.Value(timestampFieldPosition)  =  DateTime.Now
       End  If
End  Sub

Public  Sub  OnDelete(ByVal  obj  As  IObject)  Implements  IObjectClassEvents.OnDelete


       '  Do  nothing.
End  Sub

Public  Sub  OnChange(ByVal  obj  As  IObject)  Implements  IObjectClassEvents.OnChange


       '  Do  nothing.
End  Sub

If  the  OnCreate  method  is  used  to  define  custom  behavior,  it  might  be  necessary  to  implement  the  IObjectClassInfo  interface.
For  more  information,  see  IObjectClassInfo  and  IObjectClassInfo2 in  this  topic.

IObjectClassValidation
The  IObjectClassValidation  interface  is  used  to  implement  validation  rules  that  are  more  complex  than  out­of­the­box  rules  can
accommodate.  Examples  of  this  include  the  following:
 Fields  with  string  values  that  require  the  use  of  string  functions  for  validation
Fields  with  a  range  of  numeric  values  that  must  be  validated  using  another  field,  also  with  a  range  of  numeric  values
(making  it  unsuitable  for  subtyping)
Fields  with  values  that  are  constrained  by  a  combination  of  multiple  fields
 Fields  with  values  that  must  be  validated  by  checking  external  sources,  such  as  a  data  dictionary  table  or  the  local  file
system
 
The  following  two  methods  are  defined  by  IObjectClassValidation:
ValidateRow

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 14/36
11/6/2015 Creating class extensions

ValidateField
 
ValidateRow  is  called  after  the  geodatabase's  native  validation  has  been  completed.  Typically,  ValidateRow  will  be  implemented
to  call  ValidateField  on  each  field  requiring  custom  validation.  Both  of  these  methods  have  string  return  types.  If  the  validation
is  successful,  an  empty  string  should  be  returned;  otherwise,  a  description  of  the  error  should  be  returned.
 
The  following  code  example  shows  how  to  perform  regular  expression  matching  as  part  of  custom  validation.  A  simple  regular
expression  is  used  to  validate  e­mail  addresses;  note  that  this  expression  is  overly  simplified  for  the  example  and  might  not
conform  to  standards  in  some  cases.  It  is  assumed  that  any  class  this  would  be  applied  to  has  a  string  field  named  "Email,"  but
in  a  production  environment,  this  value  would  likely  be  stored  as  an  extension  property.
[C#]
//  The  class  extension's  class  helper.
private  IClassHelper  classHelper  =  null;

//  The  name  of  the  class's  Email  field.


private  const  String  EMAIL_FIELD  =  "Email";

//  The  index  of  the  Email  field.


private  int  emailFieldIndex  =    ‐  1;

//  A  simple  regular  expression  for  e‐mail  validation.


private  const  String  REGEX_STR  =  @"[\w‐]+@([\w‐]+\.)+[\w‐]+";

//  A  Regex  instance  created  when  the  class  extension  is  initialized.
private  Regex  regex  =  null;

public  void  Init(IClassHelper  classHelper,  IPropertySet  extensionProperties)


{
       //  Keep  a  reference  to  the  helper.
       this.classHelper  =  classHelper;

       //  Find  the  dataset's  Email  field.


       IClass  baseClass  =  classHelper.Class;
       emailFieldIndex  =  baseClass.FindField(EMAIL_FIELD);

       //  Create  the  Regex  instance.


       regex  =  new  Regex(REGEX_STR);
}

public  String  ValidateField(IRow  row,  String  fieldName)


{
       String  validationDescription  =  String.Empty;

       //  Check  that  the  Email  field  is  being  validated.


       if  (fieldName.Equals(EMAIL_FIELD))
       {
               //  Get  the  e‐mail  address.
               String  email  =  Convert.ToString(row.get_Value(emailFieldIndex));

               //  Check  the  regular  expression  for  a  match.


               if  (!regex.IsMatch(email))
               {
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 15/36
11/6/2015 Creating class extensions
               {
                       validationDescription  =  String.Format(
                               "{0}  is  not  a  valid  email  address.",  email);
               }
       }

       return  validationDescription;
}

public  String  ValidateRow(IRow  row)


{
       //  Validate  the  Email  field.
       return  ValidateField(row,  EMAIL_FIELD);
}

[VB.NET]
'  The  class  extension's  class  helper.

Private  classHelper  As  IClassHelper  =  Nothing


      
       '  The  name  of  the  class's  Email  field.
       Private  Const  EMAIL_FIELD  As  String  =  "Email"
      
       '  The  index  of  the  Email  field.
       Private  emailFieldIndex  As  Integer  =  ‐1
      
       '  A  simple  regular  expression  for  e‐mail  validation.
       Private  Const  REGEX_STR  As  String  =  "[\w‐]+@([\w‐]+\.)+[\w‐]+"
      
       '  A  Regex  instance  created  when  the  class  extension  is  initialized.
       Private  regex  As  Regex  =  Nothing
      
       Public  Sub  Init(ByVal  classHelper  As  IClassHelper,  ByVal  extensionProperties  As  IPropertySet)  _
                                       Implements  IClassExtension.Init
              
               '  Keep  a  reference  to  the  helper.
               Me.classHelper  =  classHelper
              
               '  Find  the  dataset's  Email  field.
               Dim  baseClass  As  IClass  =  classHelper.Class
               emailFieldIndex  =  baseClass.FindField(EMAIL_FIELD)
              
               '  Create  the  Regex  instance.
               regex  =  New  Regex(REGEX_STR)
       End  Sub
      
       Public  Function  ValidateField(ByVal  row  As  IRow,  ByVal  fieldName  As  String)  As  String  _
                                                                   Implements  IObjectClassValidation.ValidateField
              
               Dim  validationDescription  As  String  =  String.Empty
              
               '  Check  that  the  Email  field  is  being  validated.
               If  fieldName.Equals(EMAIL_FIELD)  Then
                       '  Get  the  e‐mail  address.
                       Dim  email  As  String  =  Convert.ToString(row.Value(emailFieldIndex))
                      
                       '  Check  the  regular  expression  for  a  match.
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 16/36
11/6/2015 Creating class extensions
                       '  Check  the  regular  expression  for  a  match.
                       If  Not  regex.IsMatch(email)  Then
                               validationDescription  =  String.Format("{0}  is  not  a  valid  email  address.",  email)
                       End  If
               End  If
              
               Return  validationDescription
       End  Function
      
       Public  Function  ValidateRow(ByVal  row  As  IRow)  As  String  _
                                                               Implements  IObjectClassValidation.ValidateRow
              
               '  Validate  the  Email  field.
               Return  ValidateField(row,  EMAIL_FIELD)
       End  Function

Fields  are  regularly  accessed  in  the  methods  of  several  class  extension  interfaces,  such  as  the
IObjectClassValidation.ValidateField  method  in  the  preceding  code  example  and  the  IObjectClassEvents.OnCreate  method  in  the
next  code  example.  Finding  a  field's  index  during  a  method  that  can  be  called  repeatedly  is  strongly  discouraged,  as  doing  so
during  the  bulk  validation  or  creation  of  objects  can  negatively  affect  performance.  Instead,  determine  the  field  index  during  the
IClassExtension.Init  method  and  store  it  in  a  member  variable.

IObjectClassInfo and IObjectClassInfo2
The  IObjectClassInfo  and  IObjectClassInfo2  interfaces  provide  the  following  methods  that  indicate  how  the  data  of  an  object
class  should  be  created  and  modified:
CanBypassStoreMethod—Indicates  if  IRow.Store  must  be  called  when  objects  are  created  in  the  class
CanBypassEditSession—Indicates  if  the  class  requires  data  modification  to  take  place  in  an  edit  session
 
Although  CanBypassStoreMethod  and  CanBypassEditSession  are  accessed  through  the  class,  if  IObjectClassInfo  and
IObjectClassInfo2  are  implemented  by  an  extension,  the  class  defers  its  response  to  that  of  the  extension.
By  default,  CanBypassStoreMethod  returns  true  for  object  classes  and  simple  feature  classes,  and  false  for  feature  classes  with
complex  behavior.  Classes  with  complex  behavior  often  require  the  Store  method  to  be  called,  as  it  triggers  the
IObjectClassEvents.OnCreate  method.  CanBypassStoreMethod  is  called  by  insert  cursors  when  objects  are  added  to  a  class;  if  it
returns  true,  Store  will  not  be  called  by  the  cursor. 
Insert  cursors  are  used  throughout  ArcGIS  Desktop  applications,  such  as  in  the  ArcCatalog  Simple  Data  Loader  and  in
geoprocessing  tools.  If  a  class  extension  implements  the  IObjectClassEvents  interface  and  has  important  functionality  in  the
OnCreate  method,  or  the  class  has  other  listeners  of  IObjectClassEvents,  implement  this  method  and  it  returns  false.  The
following  code  example  shows  a  typical  implementation  of  this  method:
 
[C#]
public  Boolean  CanBypassStoreMethod()
{
       return  false;
}

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 17/36
11/6/2015 Creating class extensions

[VB.NET]
Public  Function  CanBypassStoreMethod()  As  Boolean  Implements  IObjectClassInfo.CanBypassStoreMethod
       Return  False
End  Function

In  addition  to  cases  where  custom  behavior  is  defined  by  a  class  extension,  it  might  be  necessary  to  implement
CanBypassStoreMethod  if  an  editor  extension  is  listening  for  events  from  a  specific  class.  If  IRow.Store  is  not  called  when  an
object  is  created  or  modified,  geodatabase  events  will  not  be  passed  to  the  editor  extension.  For  example,  this  can  occur  when
using  ArcMap's  Object  Loader,  which  by  default,  will  not  call  IRow.Store  for  simple  feature  classes.  If  an  editor  extension
depends  on  the  reception  of  these  events,  the  class  should  be  given  an  extension  and  the  extension's  CanBypassStoreMethod
returns  false.
 
Alternatively,  the  IWorkspaceEditControl  interface  can  be  used  to  specify  that  Store  should  be  called  when  editing  any  class  in  a
workspace.
The  CanBypassEditSession  method  indicates  whether  a  class  requires  objects  to  be  created,  deleted,  or  changed  outside  of  an
edit  session.  Some  classes,  such  as  those  participating  in  a  network,  require  an  edit  session  to  ensure  proper  multiuser  behavior
and  the  correct  management  of  objects  internally  cached  database  states.  If  a  class  extension  requires  edit  events  to  be  handled
(such  as  those  from  the  IWorkspaceEditEvents interface)  to  validate  or  modify  classes  or  private  datasets,  implement  this
method  and  it  returns  false.  Doing  so  prevents  applications  from  editing  the  class  outside  an  edit  session.  The  following  code
example  is  a  typical  implementation  of  this  method:
 
[C#]
public  Boolean  CanBypassEditSession()
{
       return  false;
}

[VB.NET]
Public  Function  CanBypassEditSession()  As  Boolean  Implements  IObjectClassInfo2.CanBypassEditSession
       Return  False
End  Function

Class  policies—whether  it  requires  the  Store  method  or  an  edit  session—can  only  be  tightened  by  these  methods.  For  example,  a
feature  class  that  participates  in  a  topology  must  be  edited  in  an  edit  session,  and  implementing  a  class  extension  that  returns
true  from  the  CanByPassEditSession  method  will  not  change  this.

IRelatedObjectClassEvents and IRelatedObjectClassEvents2
Use  the  IRelatedObjectClassEvents  and  IRelatedObjectClassEvents2  interfaces  to  handle  editing  events  from  a  class  that  is
related  through  a  relationship  class  to  the  extension's  class.  The  former  interface  defines  only  a  single  method,
RelatedObjectCreated,  which  is  called  when  a  new  object  is  created  in  a  related  class.  The  latter  defines  several  more  methods,
most  notably  RelatedObjectChanged,  which  is  called  when  an  object  in  a  related  class  is  modified,  as  well  as  four  other  methods
that  are  triggered  by  calls  to  the  IFeatureEdit interface.
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 18/36
11/6/2015 Creating class extensions

 
For  any  of  these  methods  to  be  called  on  a  class  extension,  the  proper  notification  must  be  enabled  in  the  relationship  class.  If
the  extension  is  on  the  origin  class,  notification  must  be  set  to  Backward  or  Both,  and  if  the  extension  is  on  the  destination
class,  notification  must  be  set  to  Forward  or  Both.
 
Unlike  many  similarly  named  interfaces,  IRelatedObjectClassEvents2  does  not  inherit  from  IRelatedObjectClassEvents.  For  a
class  extension  to  define  event  handlers  for  both,  it  must  explicitly  implement  both.
In  most  cases,  creating  a  class  extension  for  the  source  of  these  events  and  implementing  the  IObjectClassEvents  interface  is
the  best  way  to  provide  this  functionality.  The  following  are  two  typical  scenarios  where  implementing  a  class  extension  that
listens  for  related  object  class  events  is  useful:
When  the  source  class  already  has  a  class  extension  applied  to  it.
When  creating  a  variation  of  composite  relationship  behavior.  For  example,  creating  a  relationship  class  that  will  move  and
rotate  related  features,  but  will  not  cascade  deletion.
 
The  RelatedObjectSetMoved and  RelatedObjectSetRotated methods  can  be  implemented  if  a  transformation  of  the  related  object's
geometry  needs  to  be  reflected  in  the  extension's  class.  This  is  particularly  useful  in  a  relationship  between  two  feature  classes,
for  example,  a  relationship  class  with  a  feature  class  of  poles  and  a  feature  class  of  transformers.  If  a  pole  is  moved  or  rotated
and  one  or  more  transformers  are  attached  to  that  pole,  the  transformers  should  move  or  rotate  with  it.  This  can  also  be  useful
in  a  relationship  between  a  feature  class  and  an  object  class,  for  example,  if  an  object's  attributes  are  derived  from  a  related
feature's  geometry.
 
The  following  code  example  shows  how  to  use  the  IRelatedObjectClassEvents2  interface  to  create  this  variation  of  composite
relationship  behavior:
[C#]
public  void  RelatedObjectSetMoved(IRelationshipClass  relationshipClass,  ISet
       objectsThatNeedToChange,  ISet  objectsThatChanged,  ILine  moveVector)
{
       //  Get  the  first  object  to  change  and  cast  to  the  IFeatureEdit  interface.
       objectsThatNeedToChange.Reset();
       IFeatureEdit  featureEdit  =  objectsThatNeedToChange.Next()as  IFeatureEdit;

       //  If  it  is  the  correct  type  of  object,  move  the  related  objects.
       if  (featureEdit  !=  null)
       {
               featureEdit.MoveSet(objectsThatNeedToChange,  moveVector);
       }
}

public  void  RelatedObjectSetRotated(IRelationshipClass  relationshipClass,  ISet


       objectsThatNeedToChange,  ISet  objectsThatChanged,  IPoint  origin,  Double  angle)
{
       //  Get  the  first  object  to  change  and  cast  to  the  IFeatureEdit  interface.
       objectsThatNeedToChange.Reset();
       IFeatureEdit  featureEdit  =  objectsThatNeedToChange.Next()as  IFeatureEdit;

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 19/36
11/6/2015 Creating class extensions

       //  If  it  is  the  correct  type  of  object,  move  the  related  objects.
       if  (featureEdit  !=  null)
       {
               featureEdit.RotateSet(objectsThatNeedToChange,  origin,  angle);
       }
}

[VB.NET]
Public  Sub  RelatedObjectSetMoved(ByVal  relationshipClass  As  IRelationshipClass,  _
                                                                 ByVal  objectsThatNeedToChange  As  ISet,  ByVal  objectsThatChanged  As  ISet,  _
                                                                 ByVal  moveVector  As  ILine)  Implements  IRelatedObjectClassEvents2.RelatedObjectSetMoved
      
       '  Get  the  first  object  to  change  and  cast  to  the  IFeatureEdit  interface.
       objectsThatNeedToChange.Reset()
       Dim  featureEdit  As  IFeatureEdit  =  TryCast(objectsThatNeedToChange.Next(),  IFeatureEdit)
      
       '  If  it  is  the  correct  type  of  object,  move  the  related  objects.
       If  Not  featureEdit  Is  Nothing  Then
               featureEdit.MoveSet(objectsThatNeedToChange,  moveVector)
       End  If
End  Sub

Public  Sub  RelatedObjectSetRotated(ByVal  relationshipClass  As  IRelationshipClass,  _


                                                                     ByVal  objectsThatNeedToChange  As  ISet,  ByVal  objectsThatChanged  As  ISet,  _
                                                                     ByVal  origin  As  IPoint,  ByVal  angle  As  Double)  Implements  
IRelatedObjectClassEvents2.RelatedObjectSetRotated
      
       '  Get  the  first  object  to  change  and  cast  to  the  IFeatureEdit  interface.
       objectsThatNeedToChange.Reset()
       Dim  featureEdit  As  IFeatureEdit  =  TryCast(objectsThatNeedToChange.Next(),  IFeatureEdit)
      
       '  If  it  is  the  correct  type  of  object,  move  the  related  objects.
       If  Not  featureEdit  Is  Nothing  Then
               featureEdit.RotateSet(objectsThatNeedToChange,  origin,  angle)
       End  If
End  Sub

The  last  two  methods  that  must  be  implemented  to  honor  the  interface  are  RelatedObjectMoved and  RelatedObjectRotated.  These
methods  are  currently  reserved  and  should  not  define  any  functionality.
 
If  a  class  with  an  extension  that  implements  IRelatedObjectClassEvents  or  IRelatedObjectClassEvents2  is  going  to  participate  in
multiple  relationship  classes,  it  is  recommended  that  the  IConfirmSendRelatedObjectEvents  interface  be  implemented  in  tandem.
For  more  information,  see  IConfirmSendRelatedObjectEvents in  this  topic.
There  might  not  be  a  1:1  relationship  between  the  objects  contained  by  the  set  parameters  of  these  methods;
therefore,  iterating  through  the  set  of  origin  class  objects  and  the  set  of  destination  class  objects  in  parallel  (and  assuming  a
relationship  exists)  is  not  recommended.  For  example,  if  the  relationship  class  has  1:M  cardinality,  there  can  be  several  objects
in  the  objectsThatNeedToChange  set  that  are  related  to  a  single  object  in  the  objectsThatChanged  set.
 
These  events  are  triggered  from  the  IFeatureEdit  interface,  which  is  called  by  the  ArcMap  editor  when  features  or  sets  of
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 20/36
11/6/2015 Creating class extensions

features  are  moved  or  rotated,  but  not  when  they  are  reshaped  (the  RelatedObjectChanged  event  is  called  in  that  case).  Also,  if
the  related  object's  geometry  is  modified  directly  at  the  geometry  level,  for  example,  by  using  the  ITransform2D.Rotate or
ITransform2D.Move methods,  these  events  will  not  be  triggered.

IConfirmSendRelatedObjectEvents
Implement  the  IConfirmSendRelatedObjectEvents  interface  to  filter  notifications  received  by  the  extension  from  any  related
classes.  It  consists  of  five  methods  with  Boolean  return  values,  each  of  which  corresponds  to  a  method  in  the
IRelatedObjectClassEvents2  interface.  If  a  class  extension  implements  these  and  a  method  returns  false,  the  corresponding
IRelatedObjectClassEvents2  method  will  not  be  called,  effectively  "short­circuiting"  the  notification.
 
Despite  the  name  of  the  interface  and  methods,  apply  extensions  that  implement  this  interface,  not  to  the  source  of  the
notifications  but  the  receiver.  This  can  be  thought  of  as  confirming  the  reception  of  a  notification  rather  than  the  transmission.
A  common  situation  where  this  interface  can  be  implemented  is  when  change  notifications  should  only  be  handled  if  a  specific
field  of  an  object  is  changed  (that  is,  the  Shape  field).  By  using  the  IRowChanges or  IFeatureChanges interface,  these  methods
can  determine  whether  the  notification  is  relevant.  Another  situation  where  this  can  be  useful  is  if  notification  is  dependent  on
the  source  object's  subtype.
 
This  interface  should  also  be  implemented  if  a  class  is  receiving  notifications  from  multiple  related  classes  and  if  events  are
only  relevant  from  a  specific  class.  This  can  be  done  by  checking  the  name  of  the  relationship  class  when  confirmation  begins.
If  hard  coding  a  relationship  class  name  is  not  ideal,  build  a  custom  property  page  to  save  the  relationship  class  name  as  an
extension  property.
 
The  following  code  example  shows  how  to  restrict  change  notifications  to  those  where  a  feature's  geometry  has  been  modified.
Use  this  in  a  feature  class  extension,  as  it  has  no  effect  in  an  object  class  extension.
 
[C#]
//  The  name  of  the  ownership  relationship  class.  TODO:  This  should  be  set  by  implementing  an
//  extension  specific  method,  along  with  a  property  page,  and  stored  in  the  extension  properties.
private  String  ownershipRelClassName  =  null;

public  Boolean  ConfirmSendRelatedObjectChanged(IRelationshipClass  relClass,  IObject


       objectThatChanged)
{
       //  Make  sure  the  object  changed  is  from  the  correct  related  class.
       IDataset  dataset  =  (IDataset)relClass;
       if  (!dataset.Name.Equals(ownershipRelClassName))
       {
               return  false;
       }

       //  Cast  to  the  IFeatureChanges  interface  and  check  for  shape  change.
       IFeatureChanges  featureChanges  =  objectThatChanged  as  IFeatureChanges;
       if  (featureChanges  !=  null)
       {
               return  featureChanges.ShapeChanged;
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 21/36
11/6/2015 Creating class extensions
               return  featureChanges.ShapeChanged;
       }

       //  Object  is  not  a  feature.


       return  false;
}

[VB.NET]
'  The  name  of  the  ownership  relationship  class.  TODO:  This  should  be  set  by  implementing  an
'  extension  specific  method,  along  with  a  property  page,  and  stored  in  the  extension  properties.
Private  ownershipRelClassName  As  String  =  Nothing

Public  Function  ConfirmSendRelatedObjectChanged(ByVal  relClass  As  IRelationshipClass,  ByVal  objectThatChanged  As  IObject)  As  Boolean  


Implements  IConfirmSendRelatedObjectEvents.ConfirmSendRelatedObjectChanged
       '  Make  sure  the  object  changed  is  from  the  correct  related  class.
       Dim  dataset  As  IDataset  =  CType(relClass,  IDataset)
       If  Not  dataset.Name.Equals(ownershipRelClassName)  Then
               Return  False
       End  If
      
       '  Cast  to  the  IFeatureChanges  interface  and  check  for  shape  change.
       Dim  featureChanges  As  IFeatureChanges  =  TryCast(objectThatChanged,  IFeatureChanges)
       If  Not  featureChanges  Is  Nothing  Then
               Return  featureChanges.ShapeChanged
       End  If
      
       '  Object  is  not  a  feature.
       Return  False
End  Function

IObjectInspector
The  Attributes  dialog  box  in  ArcMap  is  used  to  view  and  edit  an  object's  attributes  during  an  edit  session.  It  contains  a  tree
view,  which  shows  the  currently  selected  objects  and  a  list  view,  which  contains  the  names  and  values  for  each  field  of  the
object  selected  in  the  tree  view.  The  list  view  is  the  default  object  inspector  or  feature  inspector  (the  terms  are
interchangeable).
 
See  the  following  screen  shot  that  shows  the  Attributes  dialog  box  with  the  default  object  inspector:

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 22/36
11/6/2015 Creating class extensions

 
The  IObjectInspector  interface  allows  the  creation  of  a  custom  feature  inspector  as  part  of  a  class  extension.  Custom  feature
inspectors  can  offer  a  more  application  specific  editing  experience,  for  example,  providing  calendar  controls  to  edit  date  values,
displaying  raster  images,  or  providing  an  OpenFileDialog  for  fields  that  expect  local  file  names.
 
A  feature  inspector  should  not  be  used  as  the  primary  method  of  restricting  user  input,  such  as  using  radio  buttons  or  combo
boxes.  While  these  can  be  applicable  to  the  class's  schema,  view  form  level  logic  as  a  supplement  to  domains,  subtypes,  and
validation  rules  and  not  a  replacement.  
 
For  an  example  of  a  class  extension  that  provides  a  custom  feature  inspector,  see  the  Tabbed  feature  inspector  sample.
 
The  buttons  at  the  top  of  the  Attributes  dialog  box—for  example,  for  sorting—will  not  have  any  effect  when  used  with  a  custom
feature  inspector.

IFeatureClassEdit
Use  the  IFeatureClassEdit  interface  for  specifying  advanced  editing  configuration  for  a  feature  class  or  object  class  (has  two
properties,  CanEditWithProjection and  CustomSplitPolicyForRelationship,  and  one  method,  HasCustomSplitPolicyForRelationship). 
 

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 23/36
11/6/2015 Creating class extensions

ArcMap  supports  the  editing  of  simple  features  in  a  different  spatial  reference  than  that  of  the  feature  class.  If  the  associated
feature  class  contains  simple  features,  editing  of  the  feature  class  in  a  different  spatial  reference  can  be  prevented  by
implementing  the  CanEditWithProjectionproperty  and  returning  false.  See  the  following  code  example  for  a  typical
implementation: 
 
[C#]
public  Boolean  CanEditWithProjection
{
       get
       {
               return  false;
       }
}

[VB.NET]
Public  ReadOnly  Property  CanEditWithProjection()  As  Boolean  Implements  IFeatureClassEdit.CanEditWithProjection
Get
Return  False
End  Get
End  Property

When  a  feature  with  related  objects  is  split,  the  geodatabase  can  delete  the  related  objects,  create  relationships,  or  only
maintain  the  relationships  with  the  larger  portion  of  the  split  feature,  depending  on  the  type  and  cardinality  of  the  relationship
class.  If  the  default  split  policy  is  not  the  desired  behavior,  return  true  from  HasCustomSplitPolicy.  The
CustomSplitPolicyForRelationship  property  can  then  be  used  to  specify  a  custom  split  policy  according  to  the  relationship  class
and  properties,  such  as  subtype,  of  the  feature  being  split.  If  this  interface  is  implemented  solely  for  the  CanEditWithProjection
property,  false  is  returned  (and  the  split  policy  property  can  return  anything,  as  it  will  not  be  called).
 
An  example  of  when  this  would  be  useful  is  with  a  relationship  class  between  parcels  and  owners.  If  the  relationship  class  is
simple  and  has  1:M  cardinality,  when  a  parcel  is  divided,  the  owner  remains  related  to  the  larger  of  the  two  new  parcels,  but
the  smaller  will  not  have  an  owner.  The  following  code  example  shows  how  to  modify  this  behavior  so  that  both  parts  of  the
parcel  remains  related  to  the  owner:
 
[C#]
//  Load  from  extension  properties  in  IClassExtension.Init.
private  String  parcelOwnerRelClassName  =  null;

public  Boolean  HasCustomSplitPolicyForRelationship()


{
       return  true;
}

public  esriRelationshipSplitPolicy  get_CustomSplitPolicyForRelationship(IRow  row,


       IRelationshipClass  relClass)
{
       IDataset  rcDataset  =  (IDataset)relClass;
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 24/36
11/6/2015 Creating class extensions
       IDataset  rcDataset  =  (IDataset)relClass;
       if  (rcDataset.Name.Equals(parcelOwnerRelClassName))
       {
               //  If  the  relationship  class  (RC)  is  the  parcel  owner  RC,  use  the  custom  policy.
               return  esriRelationshipSplitPolicy.esriRSPPreserveOnAll;
       }
       else
       {
               //  It  is  another  RC.  Use  the  default  policy.
               if  (relClass.IsComposite)
               {
                       return  esriRelationshipSplitPolicy.esriRSPDeleteParts;
               }
               else
               {
                       return  esriRelationshipSplitPolicy.esriRSPPreserveOnLargest;
               }
       }
}

[VB.NET]
Public  Function  HasCustomSplitPolicyForRelationship()  As  Boolean  Implements  IFeatureClassEdit.HasCustomSplitPolicyForRelationship
       Return  True
End  Function

Public  ReadOnly  Property  CustomSplitPolicyForRelationship(ByVal  row  As  IRow,  ByVal  relClass  As  IRelationshipClass)  As  


esriRelationshipSplitPolicy  Implements  IFeatureClassEdit.CustomSplitPolicyForRelationship
Get
Dim  rcDataset  As  IDataset  =  CType(relClass,  IDataset)
If  rcDataset.Name.Equals(ownershipRelClassName)  Then
       '  If  the  relationship  class  (RC)  is  the  parcel  owner  RC,  use  the  custom  policy.
       Return  esriRelationshipSplitPolicy.esriRSPPreserveOnAll
Else
       '  It  is  another  RC.  Use  the  default  policy.
       If  relClass.IsComposite  Then
               Return  esriRelationshipSplitPolicy.esriRSPDeleteParts
       Else
               Return  esriRelationshipSplitPolicy.esriRSPPreserveOnLargest
       End  If
End  If
End  Get
End  Property

An  extension  that  uses  this  interface  to  define  a  custom  split  policy  can  be  applied  to  the  source  or  destination  class  of  the
relationship  class.  Although  the  CanEditWithProjection  property  is  only  applicable  to  feature  class  extensions,  the  ability  to  define
a  custom  split  policy  also  makes  this  interface  relevant  to  object  class  extensions.

IFeatureClassDraw
Use  the  IFeatureClassDraw  interface  to  specify  custom  drawing  behavior  for  a  feature  class.  Custom  drawing  can  be  achieved
with  a  custom  renderer  or  by  creating  custom  features  that  implement  the  IFeatureDraw  interface.  Only  implement  this  interface
in  a  feature  class  extension.
ArcGIS  applications  with  three­dimensional  (3D)  rendering  (that  is,  ArcGlobe,  ArcScene,  and  ArcGIS  Explorer)  might  not  honor
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 25/36
11/6/2015 Creating class extensions

custom  rendering  defined  by  a  feature  class  extension.


An  important  point  to  remember  is  that  custom  renderers  can  be  used  by  feature  classes  without  a  feature  class  extension.
Associating  a  custom  renderer  with  an  extension  is  only  required  if  the  feature  class  should  be  rendered  exclusively  by  a  certain
type  of  renderer,  or  if  a  renderer  is  kept  "private"  by  not  registering  its  property  page  in  the  appropriate  component  category.  A
custom  property  page  is  still  required  for  this  interface  to  implement  correctly,  but  it  is  not  necessary  to  be  registered  on  the
ESRI  Renderer  Property  Pages  component  category.  For  more  information  on  custom  renderers,  see  Creating  custom  feature
renderers.
 
The  simplest  method  to  implement  is  DoesCustomDrawing.  It  has  a  Boolean  return  type  but  should  always  return  true.  The
following  is  a  typical  code  example:
 
[C#]
public  Boolean  DoesCustomDrawing()
{
       return  true;
}

[VB.NET]
Public  Function  DoesCustomDrawing()  As  Boolean  Implements  IFeatureClassDraw.DoesCustomDrawing
       Return  True
End  Function

The  HasCustomRenderer  method  and  ExclusiveCustomRenderer  property  have  Boolean  return  types  and  are  also  easy  to
implement.
 HasCustomRenderer  returns  true  if  the  custom  drawing  behavior  is  implemented  with  a  custom  renderer  and  returns  false
if  the  behavior  is  defined  in  a  custom  feature.
 ExclusiveCustomRenderer  returns  true  if  the  custom  renderer  is  the  only  renderer  that  layers  can  use  when  the  feature
class  displays  (false  allows  others  to  be  used).
 
If  an  exclusive  custom  renderer  is  defined  but  the  specified  renderer  is  not  available  to  a  client,  the  client  uses  the  default
renderer  (in  ArcMap,  the  Single  Symbol  renderer).  The  following  is  a  typical  code  example:
 
[C#]
public  Boolean  ExclusiveCustomRenderer
{
       get
       {
               return  false;
       }
}

public  Boolean  HasCustomRenderer()


{
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 26/36
11/6/2015 Creating class extensions
{
       return  true;
}

[VB.NET]
Public  ReadOnly  Property  ExclusiveCustomRenderer()  As  Boolean  Implements  IFeatureClassDraw.ExclusiveCustomRenderer
Get
Return  True
End  Get
End  Property

Public  Function  HasCustomRenderer()  As  Boolean  Implements  IFeatureClassDraw.HasCustomRenderer


       Return  True
End  Function

It  is  recommended  that  a  feature  class  extension  defining  a  custom  drawing  be  applied  before  the  feature  class  is  included  in
ArcMap  documents  or  layer  files.  If  these  files  include  the  feature  class  before  the  application  of  an  extension  that  defines  a
custom  renderer  as  exclusive,  these  files  will  not  honor  the  extension's  specifications.
CustomRenderer  and  CustomRendererPropPageCLSID  define  the  renderer  used.  CustomRenderer  returns  an  instance  of  the
renderer  associated  with  the  class  and  CustomRendererPropPageCLSID  returns  a  unique  identifier  (UID)  instance  for  the
renderer's  property  page.  If  the  custom  drawing  is  implemented  through  a  custom  feature  and  not  a  custom  renderer,  null  can
be  returned.  See  the  following  code  example:
 
[C#]
public  object  CustomRenderer
{
       get
       {
               Type  type  =  Type.GetTypeFromProgID("PointDispersal.Renderer");
               return  Activator.CreateInstance(type);
       }
}

public  UID  CustomRendererPropPageCLSID


{
       get
       {
               UID  uid  =  new  UIDClass();
               uid.Value  =  "{CB3B689F‐27A5‐11D7‐8B5C‐00104BB6FCCB}";
               return  uid;
       }
}

[VB.NET]
Public  ReadOnly  Property  CustomRenderer()  As  Object  Implements  IFeatureClassDraw.CustomRenderer
Get
Dim  Type  As  Type  =  Type.GetTypeFromProgID("PointDispersal.Renderer")
Return  Activator.CreateInstance(Type)
End  Get
End  Property
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 27/36
11/6/2015 Creating class extensions
End  Property

Public  ReadOnly  Property  CustomRendererPropPageCLSID()  As  UID  Implements  IFeatureClassDraw.CustomRendererPropPageCLSID


Get
Dim  uid  As  UID  =  New  UIDClass()
uid.Value  =  "{CB3B689F‐27A5‐11D7‐8B5C‐00104BB6FCCB}"
Return  uid
End  Get
End  Property

The  final  property  is  only  important  if  custom  drawing  is  implemented  through  custom  features.  RequiredFieldsForDraw
specifies  the  fields'  (other  than  the  Shape  field)  features  required  in  their  implementation  of  IFeatureDraw.Draw.  By  default,  the
feature  cursor  used  in  the  drawing  process  only  retrieves  the  features'  geometries.  If  others  are  required,  they  should  be
returned  as  a  fields  collection  by  this  property.  The  following  code  example  is  suitable  in  a  scenario  where  the  ObjectID  (OID)
field  is  used  by  the  custom  feature:
 
[C#]
public  IFields  RequiredFieldsForDraw
{
       get
       {
               //  Get  the  class's  OID  field.
               IClass  baseClass  =  classHelper.Class;
               String  oidFieldName  =  baseClass.OIDFieldName;
               int  oidFieldIndex  =  baseClass.FindField(oidFieldName);
               IFields  baseClassFields  =  baseClass.Fields;
               IField  oidField  =  baseClassFields.get_Field(oidFieldIndex);

               //  Create  a  new  fields  collection.


               IFields  fields  =  new  FieldsClass();
               IFieldsEdit  fieldsEdit  =  (IFieldsEdit)fields;
               fieldsEdit.AddField(oidField);

               return  fields;
       }
}

[VB.NET]
Public  ReadOnly  Property  RequiredFieldsForDraw()  As  IFields  Implements  IFeatureClassDraw.RequiredFieldsForDraw
Get
'  Get  the  class's  OID  field.
Dim  baseClass  As  IClass  =  classHelper.Class
Dim  oidFieldName  As  String  =  baseClass.OIDFieldName
Dim  oidFieldIndex  As  Integer  =  baseClass.FindField(oidFieldName)
Dim  baseClassFields  As  IFields  =  baseClass.Fields
Dim  oidField  As  IField  =  baseClassFields.Field(oidFieldIndex)

'  Create  a  new  fields  collection.


Dim  fields  As  IFields  =  New  FieldsClass()
Dim  fieldsEdit  As  IFieldsEdit  =  CType(fields,  IFieldsEdit)
fieldsEdit.AddField(oidField)

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 28/36
11/6/2015 Creating class extensions

Return  fields
End  Get
End  Property

Creating custom class descriptions
Class  descriptions  provide  applications  and  developers  with  a  template  for  dataset  creation.  Two  frequently  used  examples  of
this  are  object  class  descriptions  and  feature  class  descriptions,  both  included  with  ArcGIS.  ArcCatalog  uses  these  to  determine
the  required  fields  of  a  new  object  or  feature  class,  and  their  instance  of  class  identifiers  (CLSIDs)  and  extension  CLSIDs.
ArcGIS  also  includes  other  class  descriptions  for  classes,  such  as  annotation,  dimensions,  and  raster  catalogs.  Creating  a  feature
class  description  makes  a  new  type  of  feature  class  visible  to  ArcGIS  and  both  object  and  feature  class  descriptions  are
convenient  ways  for  developers  to  access  information  about  the  class.
If  the  new  class  type  contains  nonspatial  data,  the  description  class  should  implement  the  IObjectClassDescription interface  and
if  it  contains  features,  it  should  also  implement  the  IFeatureClassDescription interface.  Like  a  class  extension,  a  class  description
requires  component  category  registration  but  should  be  registered  to  the  GeoObjectClassDescriptions  category  rather  than  the
GeoObjectClassExtensions  category.
The  name  properties  of  a  class  description  are  easy  to  implement.  The  following  are  the  name  properties  that  are  required  for  a
description:
Name—Returns  what  users  see  in  the  Type  section  of  the  ArcCatalog  New  Feature  Class  dialog  box  when  creating  a  new
feature  class
AliasName—Provides  an  alternate  name  for  the  object  class  description
ModelName—Provides  an  additional  way  of  guaranteeing  a  class  is  unique
In  most  cases,  the  AliasName  and  ModelName  properties  are  unused  and  it  is  safe  to  return  empty  strings.  In  addition  to  the
three  previously  mentioned  properties,  the  ModelNameUnique property  indicates  if  the  model  name  is  unique.  If  a  blank  model
name  is  used,  false  is  returned.
The  following  code  example  shows  a  typical  implementation  of  the  Name,  AliasName,  ModelName,  and  ModelNameUnique
properties:
[C#]
public  String  Name
{
       get
       {
               return  "Timestamped  Class";
       }
}

public  String  AliasName


{
       get
       {
               return  String.Empty;
       }
}

public  String  ModelName


{
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 29/36
11/6/2015 Creating class extensions
{
       get
       {
               return  String.Empty;
       }
}

public  Boolean  ModelNameUnique


{
       get
       {
               return  false;
       }
}

[VB.NET]
Public  ReadOnly  Property  Name()  As  String  Implements  IObjectClassDescription.Name
Get
Return  "Timestamped  Class"
End  Get
End  Property

Public  ReadOnly  Property  AliasName()  As  String  Implements  IObjectClassDescription.AliasName


Get
Return  ""
End  Get
End  Property

Public  ReadOnly  Property  ModelName()  As  String  Implements  ESRI.ArcGIS.Geodatabase.IObjectClassDescription.ModelName


Get
Return  ""
End  Get
End  Property

Public  ReadOnly  Property  ModelNameUnique()  As  Boolean  Implements  ESRI.ArcGIS.Geodatabase.IObjectClassDescription.ModelNameUnique


Get
Return  False
End  Get
End  Property

The  InstanceCLSID and  ClassExtensionCLSID properties  return  UID instances  containing  the  GUIDs  of  the  classes'  objects  (or
features)  and  of  the  classes'  extension,  respectively.  Many  classes  return  UIDs  containing  the  GUIDs  of  the  object  or  feature
class,  but  classes  designed  to  use  custom  features  return  a  UID  containing  the  value  of  the  custom  feature's  GUID.  The
ClassExtensionCLSID  property  returns  a  UID  containing  the  appropriate  class  extension's  GUID.  The  following  code  example
shows  a  typical  implementation  of  these  two  properties:
 
[C#]
public  UID  InstanceCLSID
{
       get
       {

               //  Return  the  UID  of  feature.


http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 30/36
11/6/2015 Creating class extensions
               //  Return  the  UID  of  feature.
               UID  uid  =  new  UIDClass();
               uid.Value  =  "{52353152‐891A‐11D0‐BEC6‐00805F7C4268}";
               return  uid;
       }
}

public  UID  ClassExtensionCLSID


{
       get
       {
               //  Return  the  UID  of  TimestampedClassExtension.
               UID  uid  =  new  UIDClass();
               uid.Value  =  "{31b0b791‐3606‐4c58‐b4d9‐940c157dca4c}";
               return  uid;
       }
}

[VB.NET]
Public  ReadOnly  Property  InstanceCLSID()  As  UID  Implements  IObjectClassDescription.InstanceCLSID
Get
Dim  uid  As  UID  =  New  UIDClass()
uid.Value  =  "{52353152‐891A‐11D0‐BEC6‐00805F7C4268}"
Return  uid
End  Get
End  Property

Public  ReadOnly  Property  ClassExtensionCLSID()  As  UID  Implements  IObjectClassDescription.ClassExtensionCLSID


Get
Dim  uid  As  UID  =  New  UIDClass()
uid.Value  =  "{31b0b791‐3606‐4c58‐b4d9‐940c157dca4c}"
Return  uid
End  Get
End  Property

RequiredFields returns  a  fields  collection  containing  the  required  fields  for  the  description's  class  type  to  operate  properly.  For
example,  an  object  class  description  returns  a  fields  collection  containing  one  ObjectID  field,  whereas  a  feature  class  description
returns  an  ObjectID  field  and  a  Shape  field.  The  following  code  example  shows  an  implementation  of  this  property  for  a  time
stamped  class,  which  requires  "Created"  and  "Modified"  date  fields:
 
[C#]
public  IFields  RequiredFields
{
       get
       {
               //  Get  the  feature  class  required  fields.
               IFeatureClassDescription  fcDescription  =  new  FeatureClassDescriptionClass();
               IObjectClassDescription  ocDescription  =  (IObjectClassDescription)
                       fcDescription;
               IFields  requiredFields  =  ocDescription.RequiredFields;
               IFieldsEdit  requiredFieldsEdit  =  (IFieldsEdit)requiredFields;

               //  Add  a  created  date  field.


http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 31/36
11/6/2015 Creating class extensions
               //  Add  a  created  date  field.
               IField  createdField  =  new  FieldClass();
               IFieldEdit  createdFieldEdit  =  (IFieldEdit)createdField;
               createdFieldEdit.Name_2  =  "Created";
               createdFieldEdit.Required_2  =  false;
               createdFieldEdit.IsNullable_2  =  true;
               createdFieldEdit.Type_2  =  esriFieldType.esriFieldTypeDate;
               requiredFieldsEdit.AddField(createdField);

               //  Add  a  modified  date  field.


               IField  modifiedField  =  new  FieldClass();
               IFieldEdit  modifiedFieldEdit  =  (IFieldEdit)modifiedField;
               modifiedFieldEdit.Name_2  =  "Modified";
               modifiedFieldEdit.Required_2  =  false;
               modifiedFieldEdit.IsNullable_2  =  true;
               modifiedFieldEdit.Type_2  =  esriFieldType.esriFieldTypeDate;
               requiredFieldsEdit.AddField(modifiedField);

               return  requiredFields;
       }
}

[VB.NET]
Public  ReadOnly  Property  RequiredFields()  As  IFields  Implements  IObjectClassDescription.RequiredFields
Get
'  Get  the  feature  class  required  fields.
Dim  fcDescription  As  IFeatureClassDescription  =  New  FeatureClassDescriptionClass()
Dim  ocDescription  As  IObjectClassDescription  =  CType(fcDescription,  IObjectClassDescription)
Dim  fields  As  IFields  =  ocDescription.RequiredFields
Dim  fieldsEdit  As  IFieldsEdit  =  CType(fields,  IFieldsEdit)

'  Add  a  created  date  field.


Dim  createdField  As  IField  =  New  FieldClass()
Dim  createdFieldEdit  As  IFieldEdit  =  CType(createdField,  IFieldEdit)
createdFieldEdit.Name_2  =  "Created"
createdFieldEdit.Required_2  =  False
createdFieldEdit.IsNullable_2  =  True
createdFieldEdit.Type_2  =  esriFieldType.esriFieldTypeDate
fieldsEdit.AddField(createdField)

'  Add  a  modified  date  field.


Dim  modifiedField  As  IField  =  New  FieldClass()
Dim  modifiedFieldEdit  As  IFieldEdit  =  CType(modifiedField,  IFieldEdit)
modifiedFieldEdit.Name_2  =  "Modified"
modifiedFieldEdit.Required_2  =  False
modifiedFieldEdit.IsNullable_2  =  True
modifiedFieldEdit.Type_2  =  esriFieldType.esriFieldTypeDate
fieldsEdit.AddField(modifiedField)

Return  fields
End  Get
End  Property

If  the  class  description  is  for  a  feature  class,  the  following  properties  are  also  required  by  the  IFeatureClassDescription
interface:
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 32/36
11/6/2015 Creating class extensions

FeatureType—Returns  the  feature  type  to  be  created  (that  is,  simple,  simple  junction,  or  simple  edge)
ShapeFieldName—Returns  the  default  Shape  field  name  (by  default,  SHAPE  for  feature  classes)
 
The  following  code  example  shows  a  typical  implementation  of  these  properties:
 
[C#]
public  esriFeatureType  FeatureType
{
       get
       {
               return  esriFeatureType.esriFTSimple;
       }
}

public  String  ShapeFieldName


{
       get
       {
               IFeatureClassDescription  fcDescription  =  new  FeatureClassDescriptionClass();
               return  fcDescription.ShapeFieldName;
       }
}

[VB.NET]
Public  ReadOnly  Property  FeatureType()  As  esriFeatureType  Implements  IFeatureClassDescription.FeatureType
Get
Return  esriFeatureType.esriFTSimple
End  Get
End  Property

Public  ReadOnly  Property  ShapeFieldName()  As  String  Implements  IFeatureClassDescription.ShapeFieldName


Get
Dim  fcDescription  As  IFeatureClassDescription  =  New  FeatureClassDescription()
Return  fcDescription.ShapeFieldName
End  Get
End  Property

When  a  feature  class  description  is  implemented  and  registered  in  the  appropriate  component  category,  it  can  be  created  in
ArcCatalog.  See  the  following  screen  shot:
 

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 33/36
11/6/2015 Creating class extensions

 
In  addition  to  availability  in  ArcCatalog,  having  a  class  description  also  makes  a  developer's  job  easier,  as  descriptions  are  a
convenient  way  to  get  UIDs  and  required  fields  in  a  custom  client.  See  the  following  code  example:
 
[C#]
//  Create  an  instance  of  the  TimestampedClassDescription.
Type  tsDescriptionType  =  Type.GetTypeFromProgID(
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 34/36
11/6/2015 Creating class extensions
Type  tsDescriptionType  =  Type.GetTypeFromProgID(
       "TimestampedClassDescription.TimestampedClassDescription");
object  tsDescriptionObject  =  Activator.CreateInstance(tsDescriptionType);

//  Cast  the  description  object  to  ArcGIS  class  description  interfaces.
IFeatureClassDescription  fcDescription  =  (IFeatureClassDescription)
       tsDescriptionObject;
IObjectClassDescription  ocDescription  =  (IObjectClassDescription)tsDescriptionObject;

//  Create  a  new  feature  class  using  the  class  description.


IFeatureClass  featureClass  =  featureWorkspace.CreateFeatureClass("MyTimestampClass",
       ocDescription.RequiredFields,  ocDescription.InstanceCLSID,
       ocDescription.ClassExtensionCLSID,  esriFeatureType.esriFTSimple,
       fcDescription.ShapeFieldName,  "");

[VB.NET]
'  Create  an  instance  of  the  TimestampedClassDescription.
Dim  tsDescriptionType  As  Type  =  Type.GetTypeFromProgID("TimestampedClassDescription.TimestampedClassDescription")
Dim  tsDescriptionObject  As  Object  =  Activator.CreateInstance(tsDescriptionType)

'  Cast  the  description  object  to  ArcGIS  class  description  interfaces.
Dim  fcDescription  As  IFeatureClassDescription  =  CType(tsDescriptionObject,  IFeatureClassDescription)
Dim  ocDescription  As  IObjectClassDescription  =  CType(tsDescriptionObject,  IObjectClassDescription)

'  Create  a  new  feature  class  using  the  class  description.


Dim  featureClass  As  IFeatureClass  =  featureWorkspace.CreateFeatureClass("MyTimestampClass",  _
                                                                       ocDescription.RequiredFields,  ocDescription.InstanceCLSID,  ocDescription.ClassExtensionCLSID,  _
                                                                       esriFeatureType.esriFTSimple,  fcDescription.ShapeFieldName,  "")

See Also:
Geodatabase  extensions
Creating  workspace  extensions
How  to  register  COM  components
Listening  to  object  class  events

To  use  the  code  in  this  topic,  reference  the  following  assemblies  in  your  Visual  Studio  project.  In  the  code  files,  you  will  need
using  (C#)  or  Imports  (VB  .NET)  directives  for  the  corresponding  namespaces  (given  in  parenthesis  below  if  different  from  the
assembly  name):
ESRI.ArcGIS.ADF.Local
ESRI.ArcGIS.System (ESRI.ArcGIS.esriSystem)
ESRI.ArcGIS.Geodatabase
ESRI.ArcGIS.Geometry
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 35/36
11/6/2015 Creating class extensions

Development licensing Deployment licensing
ArcView ArcView
ArcEditor ArcEditor
ArcInfo ArcInfo
Engine Developer Kit Engine Runtime: Geodatabase Update

Page  URL:  http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/0001/000100000201000000.htm

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000201000000 36/36

Potrebbero piacerti anche