Inherit a class to remove a property and change method logic - asp.net

The following class is used in an ASP.NET application to read currencies from a database result set and add them up (e.g. show totals in US Dollars plus show totals in GB Pounds). It works in the following manner:
Read currency ID value
If currency ID exists already, increase the total for that currency
If currency ID does not exist, add it to the list with its value
Next
It works well using the CurrencyID property as the differentiator between each unique currency. However, it has now become apparent that IsoCurrencySymbol is also unique for each currency by default, and so CurrencyID is not actually needed.
So... I was wondering if it would be possible to inherit from this class and remove any reference to CurrencyID, therefore making the CompareTo method use IsoCurrencySymbol instead.
The trick is to leave the existing class as it is used extensively, but introduce a modified version without CurrencyID being needed. Is this possible to do please?
<Serializable()> _
Public Class CurrencyCounter
<Serializable()> _
Private Class CurrencyType
Implements IComparable
Public IsoCurrencySymbol As String
Public CurrencySymbol As String
Public CurrencyID As Int16
Public Amount As Decimal
Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo
If Not TypeOf (obj) Is CurrencyType Then
Throw New ArgumentException("Object is not a currency type")
Else
Dim c2 As CurrencyType = CType(obj, CurrencyType)
Return Me.CurrencyID.CompareTo(c2.CurrencyID)
End If
End Function
End Class
Private _Currencies As List(Of CurrencyType)
Public Sub New()
_Currencies = New List(Of CurrencyType)
End Sub
Private Sub AddStructToList(CurrencyID As Integer, IsoCurrencySymbol As String, CurrencySymbol As String, Amount As Decimal)
If IsoCurrencySymbol <> String.Empty AndAlso Amount > 0 Then
Dim s As New CurrencyType
s.CurrencyID = CurrencyID
s.IsoCurrencySymbol = IsoCurrencySymbol
s.CurrencySymbol = CurrencySymbol
s.Amount = Amount
_Currencies.Add(s)
End If
End Sub
Public Sub Add(CurrencyID As Integer, IsoCurrencySymbol As String, CurrencySymbol As String, Amount As Decimal)
Dim ct As CurrencyType = _Currencies.Find(Function(obj) obj.CurrencyID = CurrencyID)
If ct IsNot Nothing Then
ct.Amount += Amount
Else
AddStructToList(CurrencyID, IsoCurrencySymbol, CurrencySymbol, Amount)
End If
End Sub
Public Sub Clear()
_Currencies.Clear()
End Sub
Public Function Count() As Integer
Return _Currencies.Count
End Function
Public Function RenderTotals() As String
' ...
End Function
End Class

No, you cannot do that. The whole point of inheritance it to ensure that all derived classes, if nothing else, at least share the same public interface as their base class. If you are removing a property, then it doesn't share the same interface and is therefore incompatible and not a candidate for inheritance.
If you can't say that the derived class is a type of the base class, then you can't use inheritance. For instance, I can say that an automobile is a type of vehicle, therefore, if I had an automobile class, I could have it inherit from a vehicle class. I can't however say that an insect is a type of vehicle. Therefore, even if they share most things in common, I can't have an insect class inherit from a vehicle class.
The reason for this limitation is because inheritance allows you to treat an object as if it were the base type (via type casting). For instance:
Public Sub AddPassengerToVehicle(v As Vehicle)
v.Passengers.Add(New Passenger())
End Sub
' ...
Dim auto As New Automobile()
Dim bug As New Insect()
AddPassengerToVehicle(auto) ' Works because an automobile is a type vehicle (inherits from vehicle)
AddPassengerToVehicle(bug) ' Can't possibly work (nor should it)
So, if you are in a situation where you need to have a derived class that removes/hides one of the members of its base class, you are headed in the wrong direction. In a case like that, you would need to create a whole new class which just happens to have a very similar interface, but has no direct relationship with the first class, for instance:
Public Class Vehicle
Public Property Passengers As List(Of Passenger)
Public Property MaxSpeed As Integer
Public Function SpeedIsTooFast(speed) As Boolean
Return (speed > MaxSpeed)
End Function
End Class
Public Class Insect
Public Property MaxSpeed As Integer
Public Function SpeedIsTooFast(speed) As Boolean
Return (speed > MaxSpeed)
End Function
End Class
If you want to share functionality, such as the logic in the SpeedIsTooFast method in the above example, then there are a couple different ways to do that. This first would be to make wrapper methods which simply make calls to the other class, for instance:
Public Class Insect
Private _vehicle As New Vehicle()
Public Property MaxSpeed() As Integer
Get
Return _vehicle.MaxSpeed
End Get
Set(value As Integer)
_vehicle.MaxSpeed = value
End Set
End Property
Public Function SpeedIsTooFast(speed) As Boolean
Return _vehicle.SpeedIsTooFast(speed)
End Function
End Class
If you do it this way, it would be best to have both classes implement the same common interface so that you can use them interchangeably when necessary, for instance:
Public Interface ISelfPoweredMovingThing
Property MaxSpeed As Integer
Function SpeedIsTooFast(speed As Integer) As Boolean
End Interface
Another option would be to break out the common functionality into a third class and then use that class as the base for the other two, for instance:
Public Class SelfPoweredMovingThing
Public Property MaxSpeed As Integer
Public Function SpeedIsTooFast(speed) As Boolean
Return (speed > MaxSpeed)
End Function
End Class
Public Class Vehicle
Inherits SelfPoweredMovingThing
Public Property Passengers As List(Of Passenger)
End Class
Public Class Insect
Inherits SelfPoweredMovingThing
' Anything else specific only to insects...
End Class

Related

How to make a VB.Net Function parameter a strongly-typed property instead of just a String

Here is class I reference in this question:
Public Class Enums
Public Enum Subscription As Byte
Vendor = 1
FreeTrial = 2
Standard = 3
Enterprise = 4
End Enum
End Class
In a VB.NET class I have the following property:
Private _optionSelection1 As String 'added by StackOverflow EDIT
Public Property OptionSelection() As String
Get
Return If(IsNothing(_optionSelection1), String.Empty, _optionSelection1)
End Get
Set(ByVal value As String)
_optionSelection1 = value
End Set
End Property
The property gets set from a Request.Form variable as follows: 'added by StackOverflow EDIT
Me.OptionSelection = HttpContext.Current.Request.Form("option_selection1") 'added by StackOverflow EDIT
I use this value later in a function:
Dim choiceMade As Enums.Subscription = SubscriptionOptionSelected(Me.OptionSelection)
I'm thinking the function might be stronger if its parameter could be "stronger" than String:
Private Function SubscriptionOptionSelected(ByVal value As String) As Enums.Subscription
Select Case value
Case "S10"
Return Enums.Subscription.Standard
Case "ENT"
Return Enums.Subscription.Enterprise
End Select
End Function
I've tried writing the function like the following but the compiler immediately complains:
Private Function SubscriptionOptionSelected(ByVal value As OptionSelection) As Enums.Subscription
Is there a way to use the Property as a type passed to this little function ?
What you are asking is redundant. OptionSelection is a string and the function you are calling is taking a string as an input. By saying you want the type of the parameter to be the property you are saying you want a string to be a string.
Now if that string had certain business logic that needed to be applied to it to be a valid string, then you need to create a class that can contain that business logic:
Public Class OptionSelection
Private _OptionString As String
Private _validStrings As String() = New String() {"S10", "ENT"}
Public Sub New(Optional ByVal AnOption As String = "S10")
If _validStrings.Contains(AnOption) Then
_OptionString = AnOption
Else
Throw New Exception("Value must be in the list of acceptable strings")
End If
End Sub
Public Property OptionSelection() As String
Get
Return _OptionString
End Get
Set(ByVal value As String)
If _validStrings.Contains(value) Then
_OptionString = value
Else
Throw New Exception("Value must be in the list of acceptable strings")
End If
End Set
End Property
Public Shared Narrowing Operator CType(ByVal input As String) As OptionSelection
Return New OptionSelection(input)
End Operator
End Class
Then your property changes to:
Private _optionSelection1 As OptionSelection
Public Property OptionSelection() As OptionSelection
Get
Return _optionSelection1
End Get
Set(ByVal value As OptionSelection)
_optionSelection1 = value
End Set
End Property
Your assignment changes to:
Me.OptionSelection = CType(HttpContext.Current.Request.Form("option_selection1"),OptionSelection)
And your function is then:
Private Function SubscriptionOptionSelected(ByVal value As OptionSelection) As Enums.Subscription
Select Case value.OptionSelection
Case "S10"
Return Enums.Subscription.Standard
Case "ENT"
Return Enums.Subscription.Enterprise
End Select
End Function
What all this code does for you is allow you to enforce what kind of strings are being stored in the OptionSelection. You can extend the allowed strings by including them in the array _validStrings.
If your application where to try and assign a string that did not exist in the _validStrings array, then an exception would be generated. So you get a kind of Business logic type safety.
Define your property as Enums.Subscription instead of String. An alternative could be to use Enum.TryParse() to validate the input for SubscriptionOptionSelected and throw an exception if the parsing fails. Here's an example of the property as the enum, although if the sole purpose of SubscriptionOptionSelected is to parse a string to an enum value then it isn't really necessary anymore.
Private _optionSelection1 As Enums.Subscription
Public Property OptionSelection() As Enums.Subscription
Get
Return _optionSelection1
End Get
Set(ByVal value As String)
_optionSelection1 = value
End Set
End Property
Private Function SubscriptionOptionSelected(ByVal value As Enums.Subscription) As Enums.Subscription
...
End Function
Here's an example where you use Enum.TryParse instead...
Private Function SubscriptionOptionSelected(ByVal value As String) As Enums.Subscription
Dim retVal As Enums.Subscription
If Not System.Enum.TryParse(Of Enums.Subscription)(value, retVal) Then
' Deal with invalid value... throw Exception maybe?
End If
Return retVal
End Function
So in your code (based on your updates) you could change your property to an enum and do this:
Me.OptionSelection = Me.SubscriptionOptionSelected(HttpContext.Current.Request.Form("option_selection1"))
This assumes that the value of Form("option_selection1") will be either the string or numeric equivalent value of your Enum elements. If the form submission values don't match, then I'm afraid you are stuck doing things as they are.

How to throw an exception in BLL when no data found in DAL

I am trying to throw an exception in my BLL when there is no corresponding carID for the license plate number I've entered in a text box.
My DAL looks like this:
Public Class DALCar
Private dc As New cars_modelDataContext
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim result = (From car In dc.Cars
Where car.License_Plate = licensePlate_input
Select car.License_Plate).Single
Return result
End Function
End Class
And this is my BLL:
Public Class BLLCar
Private DALcar As New DALCar
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim carID As String = DALcar.getCarIdByLicensePlate(chassisNo_input)
End Function
End Class
So when there is no carID with this specific license plate an exception is throwed in my DAL, but how can I throw this exception in my BLL instead of in my DAL?
Use FirstOrDefault instead of Single
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim result = (From car In dc.Cars
Where car.License_Plate = licensePlate_input
Select car.License_Plate).FirstOrDefault
Return result
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim carID As String = DALcar.getCarIdByLicensePlate(chassisNo_input)
If carID = Nothing Then
Throw New Exception(String.Format("Can't find car id for chassisNo : {0}", chassisNo_input))
End If
End Function
Because you're using Enumerable.Single in your LINQ expression. It throws an exception if there is more than one element in the sequence or if the sequence is empty.
If you can assume the sequence will always contains 0 or 1 element then you can replace Single with FirstOrDefault (see later for more on this). It'll return the first element in the sequence or Nothing if sequence is empty.
In this case you can check for Nothing in your BLL and throw the appropriate exception there.
Like this in your DAL:
Public Class DALCar
Private dc As New cars_modelDataContext
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim result = (From car In dc.Cars
Where car.License_Plate = licensePlate_input
Select car.License_Plate).FirstOrDefault
Return result
End Function
End Class
And this in your BLL:
Public Class BLLCar
Private DALcar As New DALCar
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim carID As String = DALcar.getCarIdByLicensePlate(chassisNo_input)
If carId = Nothing Then
Throw New ArgumentException("There is no match.")
End If
End Function
End Class
If your query may returns more than one element than you have to consider if this is an error or not. If it's allowed and you want to process (return) the first one then go on with FirstOrDefault. If it's an error then you should return an enumeration from your DAL and to check the number of items in your BLL (otherwise, using Single, you'll still throw inside DAL).

VB.NET: Use Class Name as Expression

I'm not sure if this is possible but I would like to associate a class name reference to a shared member method / property / variable. Consider:
Public Class UserParameters
Public Shared Reference As Object
Public Shared Function GetReference() As Object
Return Reference
End Function
End Class
In another part of the program I would like to simply call UserParameters and have it return Reference either by aliasing GetReference or the variable directly.
I am trying to emulate the Application, Request, or Session variable:
Session(0) = Session.Item(0)
Any suggestions would be greatly appreciated.
You can't return an instance member from a static method directly (the static method can't access instance members because it isn't instantiated with the rest of the class, only one copy of a static method exists).
If you need to setup a class in such a way that you can return an instance from a static method you would need to do something similar to the following:
Public Class SampleClass
Private Sub New()
'Do something here
End Sub
Public Shared Function GetSample() As SampleClass
Dim SampleClass As SampleClass
SampleClass = New SampleClass
SampleClass.Sample = "Test"
Return SampleClass
End Function
Private _SampleString As String
Public Property Sample As String
Get
Return _SampleString
End Get
Private Set(ByVal value As String)
_SampleString = value
End Set
End Property
End Class
Public Class SampleClass2
Public Sub New()
'Here you can access the sample class in the manner you expect
Dim Sample As SampleClass = SampleClass.GetSample
'This would output "Test"
Debug.Fail(Sample.Sample)
End Sub
End Class
This method is used in various places in the CLR. Such as the System.Net.WebRequest class. where it is instantiated in this manner in usage:
' Create a request for the URL.
Dim request As WebRequest = WebRequest.Create("http://www.contoso.com/default.html")

Should my validator have access to my entire model?

As the title states I'm wondering if it's a good idea for my validation class to have access to all properties from my model. Ideally, I would like to do that because some fields require 10+ other fields to verify whether it is valid or not. I could but would rather not have functions with 10+ parameters. Or would that make the model and validator too coupled with one another? Here is a little example of what I mean. This code however does not work because it give an infinite loop!
Class User
Private m_UserID
Private m_Validator
Public Sub Class_Initialize()
End Sub
Public Property Let Validator(value)
Set m_Validator = value
m_Validator.Initialize(Me)
End Property
Public Property Get Validator()
Validator = m_Validator
End Property
Public Property Let UserID(value)
m_UserID = value
End property
Public Property Get UserID()
UserID = m_Validator.IsUserIDValid()
End property End Class
Class Validator
Private m_User
Public Sub Class_Initialize()
End Sub
Public Sub Initialize(value)
Set m_User = value
End Sub
Public Function IsUserIDValid()
IsUserIDValid = m_User.UserID > 13
End Function End Class
Dim mike : Set mike = New User
mike.UserID = 123456 mike.Validator = New Validator
Response.Write mike.UserID
If I'm right and it is a good idea, how can I go a head and fix the infinite loop with the get property UserID?
Thank you.
Solution
<!-- #include file = "../lib/Collection.asp" -->
<style type="text/css">
td { padding: 4px; }
td.error
{
background: #F00F00;
}
td.warning
{
background: #FC0;
}
</style>
<%
Class UserModel
Private m_Name
Private m_Age
Private m_Height
Public Property Let Name(value)
m_Name = value
End Property
Public Property Get Name()
Name = m_Name
End Property
Public Property Let Age(value)
m_Age = value
End Property
Public Property Get Age()
Age = m_Age
End Property
Public Property Let Height(value)
m_Height = value
End Property
Public Property Get Height()
Height = m_Height
End Property
End Class
Class NameValidation
Private m_Name
Public Function Init(name)
m_Name = name
End Function
Public Function Validate()
Dim validationObject
If Len(m_Name) < 5 Then
Set validationObject = New ValidationError
Else
Set validationObject = New ValidationSuccess
End If
validationObject.CellValue = m_Name
Set Validate = validationObject
End Function
End Class
Class AgeValidation
Private m_Age
Public Function Init(age)
m_Age = age
End Function
Public Function Validate()
Dim validationObject
If m_Age < 18 Then
Set validationObject = New ValidationError
ElseIf m_Age = 18 Then
Set validationObject = New ValidationWarning
Else
Set validationObject = New ValidationSuccess
End If
validationObject.CellValue = m_Age
Set Validate = validationObject
End Function
End Class
Class HeightValidation
Private m_Height
Public Function Init(height)
m_Height = height
End Function
Public Function Validate()
Dim validationObject
If m_Height > 400 Then
Set validationObject = New ValidationError
ElseIf m_Height = 324 Then
Set validationObject = New ValidationWarning
Else
Set validationObject = New ValidationSuccess
End If
validationObject.CellValue = m_Height
Set Validate = validationObject
End Function
End Class
Class ValidationError
Private m_CSSClass
Private m_CellValue
Public Property Get CSSClass()
CSSClass = "error"
End Property
Public Property Let CellValue(value)
m_CellValue = value
End Property
Public Property Get CellValue()
CellValue = m_CellValue
End Property
End Class
Class ValidationWarning
Private m_CSSClass
Private m_CellValue
Public Property Get CSSClass()
CSSClass = "warning"
End Property
Public Property Let CellValue(value)
m_CellValue = value
End Property
Public Property Get CellValue()
CellValue = m_CellValue
End Property
End Class
Class ValidationSuccess
Private m_CSSClass
Private m_CellValue
Public Property Get CSSClass()
CSSClass = ""
End Property
Public Property Let CellValue(value)
m_CellValue = value
End Property
Public Property Get CellValue()
CellValue = m_CellValue
End Property
End Class
Class ModelValidator
Public Function ValidateModel(model)
Dim modelValidation : Set modelValidation = New CollectionClass
' Validate name
Dim name : Set name = New NameValidation
name.Init model.Name
modelValidation.Add name
' Validate age
Dim age : Set age = New AgeValidation
age.Init model.Age
modelValidation.Add age
' Validate height
Dim height : Set height = New HeightValidation
height.Init model.Height
modelValidation.Add height
Dim validatedProperties : Set validatedProperties = New CollectionClass
Dim modelVal
For Each modelVal In modelValidation.Items()
validatedProperties.Add modelVal.Validate()
Next
Set ValidateModel = validatedProperties
End Function
End Class
Dim modelCollection : Set modelCollection = New CollectionClass
Dim user1 : Set user1 = New UserModel
user1.Name = "Mike"
user1.Age = 12
user1.Height = 32
modelCollection.Add user1
Dim user2 : Set user2 = New UserModel
user2.Name = "Phil"
user2.Age = 18
user2.Height = 432
modelCollection.Add user2
Dim user3 : Set user3 = New UserModel
user3.Name = "Michele"
user3.Age = 32
user3.Height = 324
modelCollection.Add user3
' Validate all models in the collection
Dim modelValue
Dim validatedModels : Set validatedModels = New CollectionClass
For Each modelValue In modelCollection.Items()
Dim objModelValidator : Set objModelValidator = New ModelValidator
validatedModels.Add objModelValidator.ValidateModel(modelValue)
Next
%>
<table>
<tr>
<td>Name</td>
<td>Age</td>
<td>Height</td>
</tr>
<%
Dim r, c
For Each r In validatedModels.Items()
%><tr><%
For Each c In r.Items()
%><td class="<%= c.CSSClass %>"><%= c.CellValue %></td><%
Next
%></tr><%
Next
%>
</table>
Which produces
While not perfect, it's way better than what I started with. Basically, I decided to use the decorator pattern. My next step is to most likely remove the Init() function from each validate and replace it with a SetModel() function or something. That way each validate can have access to every property in my model.
Thanks all.
I usually define a validator that validates an entire model; In this case, I would have a UserValidator class that has a method that accepts a User and returns a ValidationResult, which includes a list of validation errors.
This allows you to change the User class' implementation without affecting validation (eg, you don't have to add a new method to the Validator class every time you add a new property, or change a method signature if you want to change how the UserID is validated, etc).
I think you are right in making the validator validate the entire model. To break the infinite loop, you can pass the value to the validator
Public Property Get UserID()
UserID = m_Validator.IsUserIDValid(m_userID)
End property
// in Validator
Public Function IsUserIDValid(userID)
IsUserIDValid = userID > 13
End Function
Alternatively, if you prefer encapsulation, you can add Friend functions for accessing the property without validation.
Public Property Get UserID()
UserID = m_Validator.IsUserIDValid()
End property
Friend Function GetUserID()
GetUserID = m_userID
End Function
// in Validator
Public Function IsUserIDValid()
// "private" access - to get the unvalidated property
IsUserIDValid = m_user.GetUserID > 13
End Function
A third way to do this is to separate your object from validation. The base class defines all the properites without validation. Then you define a child class that adds validation:
class User
Private m_userID
Public Property Get UserID()
UserID = m_userID
End property
End Class
class ValidatedUser inherits User
Public Overrides Property Get UserID()
if (m_userID<15)
// handle invalid case, e.g. throw exception with property that is invalid
UserID = m_userID
End Property
Public Function Validate()
' class-level validation
End Function
End Class
A final variation uses delegation to keep the basic user properties separate from the validated ones. We make User an abstract class, since we have to implementations - one with validation, and one without.
Class MustInherit User
Public MustInherit Property Get UserID()
End Class
' A simple implementation of User that provides the properties
Class DefaultUser Inherits User
Private m_UserID
Public Overrides Property Get UserID()
UserID = m_UserID
End Property
End Class
Class ValidatedUser Inherits User
private Validator m_validator
private User m_User
Public Property Let Validator(value)
Set m_Validator = value
m_Validator.Initialize(m_User)
' note that validator uses m_User - this breaks the infinite recursion
End Property
Public Overrides Property Let UserID(value)
m_User.UserID = value;
End Property
Public Overrides Property Get UserID()
UserID = m_validator.IsUserValid();
End Property
End Class
In the last example ValidatedUser looks similar to your original code, but the key difference is that ValidatedUser itself doesn't have any property values - it delegates all property accessors to the m_User object. The Validator uses the m_user object which provides simple properties without validation, so the infinite recursion goes away.
At present, validation is done when the property is retrieved. I imagine this is done because you want to validate the data before it's used, and to avoid transient validation errors as properties are assigned. In addition to property-level validation, you may want to also define a "whole object" validation method that checks all properties on your object, particularly those involved in multi-property constraints. For example, if you have the constraint A+B+C < 50, then checking A B and C as separate properties will lead to that condition (A+B+C<50) being evaluated 3 times, which is unnecessary, and also confusing since the error will appear on one specific property, when it's really a problem with all 3 properties. Your object-level validator can check this condition just once and flag an error that indicates all 3 properties are not valid.
All of the above bind the Validation to the User class, so that clients can use User without concern for validation. There are benefits and drawbacks with this approach. The benefit is transparency - client's can use User objects and get validation behind the scenes without explicitly asking for it. The downside is that it ties validation very tightly in with your model. An alternative is to completely separate validation from the User object. This not only decouples validation, but also provides for "whole-object" validation. E.g.
' User is now a simple class (like DefaultUser above '
' with just properties, no validation '
Class UserValidator
Public Function Validate(user)
' validate the given user object, return a list of
' validation errors, each validation error object
' that describes the property or properties
' that caused the validation error and why it's an error
' E.g. '
Dim ve As ValidationError
ve = new ValidationError
ve.obj = user; ' the object that failed validation
ve.property = "userID"
ve.msg = "userId must be < 15"
' potentially put several of these in a list and return to caller
End
End Class
Any code manipulating User will then have to explicitly call Validate after making changes, but this is usually not a problem, and the level of control is much better than having it done automatically. (In my experience,you almost always have to undo "automatic" actions at some point because they get in the way.)
I wrote more than I intended. I hope this is helpful!
PS: I don't do much VB, so please be lenient of the occasional syntax error. I am an OO programmer, so I know the principles are correct. And I just noticed the "asp-classic" tag - some of the examples use features that may not be available in classic asp, although the separate Validator code - the last example, should be fine on classic asp.

How to make the Asp.Net/WSE asmx page generator add the base class properties in a derived class

I have a simple base class B with 2 public properties. This class is inherited by another class D that adds another public property. The derived class is returned by a web service call. The page generated by ASP.Net looks like:
'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3074"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute([Namespace]:="")> _
Partial Public Class D
Inherits B
Private guidField As String
'''<remarks/>
Public Property Guid() As String
Get
Return Me.guidField
End Get
Set(ByVal value As String)
Me.guidField = value
End Set
End Property
End Class
'''<remarks/>
<System.Xml.Serialization.XmlIncludeAttribute(GetType(D)), _
System.Xml.Serialization.XmlIncludeAttribute(GetType(B)), _
System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3074"), _
System.SerializableAttribute(), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Xml.Serialization.XmlTypeAttribute([Namespace]:="")> _
Partial Public MustInherit Class B
Private nameField As String
Private descriptionField As String
'''<remarks/>
Public Property Name() As String
Get
Return Me.nameField
End Get
Set(ByVal value As String)
Me.nameField = value
End Set
End Property
'''<remarks/>
Public Property Description() As String
Get
Return Me.descriptionField
End Get
Set(ByVal value As String)
Me.descriptionField = value
End Set
End Property
End Class
Is there any way to show all the public properties (from class B and class D in class D)? Only class D is useful for the web service clients, class B should not be even visible.
Thank You
Have you tried the XmlTypeAttribute on class B with IncludeInSchema=False? I don't know if that would work, but it's a possibility.
XmlTypeAttribute on MSDN for .NET 2.0
You can use the XmlSchemaProviderAttribute on your type and implement a method that returns the xsd schema without the base class separation. It's a bit of work, but you can start with the existing default output and do a little copy and paste work before dropping into the method implementation.

Resources