What is the equivalent C++/CLI syntax to the following C# declaration (if such exists):
interface MyInterface
{
int MyProperty {get;}
}
interface class MyInterface
{
property int MyProperty
{
int get();
}
};
See example here
Related
I have this interface
public interface IWeighted {
int Weight { get; }
}
and this attribute
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
public class WeightAttribute : Attribute {
private readonly int m_Weight;
public int Weight => m_Weight;
public WeightAttribute(int weight = 1) {
m_Weight = weight;
}
}
Should WeightAttribute implement IWeighted as it exactly matches the contract declared within IWeighted, or should it not seeing as WeightAttribute is an attribute (intended for use on enum members alone) and as such should not be target to selection itself?
Ok, I might be punching above my pay grade here, but I'm trying to create a generic CRUD routine for and EF project. I've got most of it working but I'm flailing around on one point.
Normally you do something like this to add an entity through a context-
DBContext.MyClass.Add( p ); // p = instance of MyClass
That works fine, but since in a global method to handle all adds regardless of what class they are I'm passing in a Model as an object it would look more like this-
DBContext<whateverobject>.Add(whateverobject); // my objects is an object param passed into the method
I've tried doing a bunch of typeofs and there where T : class stuff but I'm having no luck. Any pointing in the right direction would help me out.
I'm using EF Core 2 so my options might also be more limited than EF 6.
Thanks.
The method you're looking for is DbContext's Set<T>()
Your generic repository for your generic CRUD would look something like this:
public class Repo<T> where T: class
{
private readonly DbSet<T> _set;
public Repo(DbContext dbContext)
{
_set = dbContext.Set<T>();
}
public void Add(T entity) => _set.Add(entity);
}
This example includes a maybe unusual thing:
where T: class: we have to specify that T has to be a reference type because DbSet<T> expects T to be a reference type
For generic querying you might want to use extension methods.
In order to implement a ById method you'd have to specify that the type T must have an Id property using an interface. That would look something like this:
public interface IEntity
{
int Id { get; set; }
}
public class User : IEntity
{
public int Id { get; set; }
}
public static class DbSetExtensions
{
public static T ById<T>(this DbSet<T> dbSet, int id) where T: class =>
dbSet.FirstOrDefault(entity => entity.Id == id);
}
I've created a custom view called PINControl, which shows a PIN entry with a configurable amount of digits.
The XAML I'd like to use in my ContentPage is
<local:PINControl x:Name="PIN"
PINLength="5"
PINCompleteCommand="{Binding CompletePIN}"
HorizontalOptions="CenterAndExpand" />
My BindableProperties in the PINControl are:
public class PINControl : StackLayout
{
private const int LENGTH_DEFAULT = 4;
public static readonly BindableProperty PINLengthProp = BindableProperty.Create<PINControl, int> (c => c.PINLength, LENGTH_DEFAULT);
public static readonly BindableProperty PINCompleteCommandProp = BindableProperty.Create<PINControl, ICommand> (c => c.PINCompleteCommand, null);
public ICommand PINCompleteCommand {
get { return (ICommand)GetValue (PINCompleteCommandProp); }
set { SetValue (PINCompleteCommandProp, value); }
}
public int PINLength {
get { return (int)GetValue (PINLengthProp); }
set { SetValue (PINLengthProp, value); }
}
My ViewModel contains
public ICommand CompletePIN { get; set; }
public PINViewModel ()
{
CompletePIN = new Command<string> ((pin) => {
var e = pin.ToString();
});
}
It does not seem to have a problem with the PINLength, but the PINCompleteCommand is giving me the following error:
Cannot assign property "PINCompleteCommand": type mismatch between "Xamarin.Forms.Binding" and "System.Windows.Input.ICommand"
I cannot find a solution for this problem. Can somebody help me?
There is a good practice to follow while naming BindableProperties, which is to name it propertynameProperty.
In your case, when the Xaml parser encounter this instruction
PINCompleteCommand="{Binding CompletePIN}"
it first tries to find a public static BindableProperty with name PINCompleteCommandProperty, fails, then look for a normal property named PINCompleteCommand, succeed, and try to assign the value (a Binding) to the property (an ICommand) and generate the message you are seeing.
Fix your BindableProperty naming, and you should be fine.
Not sure it's applicable to the OP situation or not, but it's worth noting that this will also arise if the ViewModel/BindingTo property is the same name as the BindableProperty name and you bind the two together.
eg.
CustomControl
-> PinLengthCommand/PinLengthCommandProperty
ViewModel
-> PinLengthCommand
Just change the name of the property on the viewmodel and it will run OK.
Is there a way to change Swift property visibility in subclass without introducing new property?
What I would like to do is (having property initialized to default value is not mandatory requirement):
public class MyBaseClass
{
private var abc: Int = 0
}
public class MyClass: MyBaseClass
{
public override var abc: Int = 0 // this cannot be compiled
}
Above code shows compiler error:
Cannot override with stored property 'abc'
The only way I can currently solve this is introducing another property but that is not what I prefer to do:
public class MyClass: MyBaseClass
{
public var abcd: Int
{
get
{
return abc
}
set
{
abc = newValue
}
}
}
Swift has two types of properties: stored properties and computed properties. You can override both of them but the overriden version cannot be a stored property, you have to override using computed properties.
Note that a stored property is just a chunk of memory but a computed property is a set of two methods - a getter and a setter. You cannot override a chunk of memory with another chunk of memory but you can override a method.
See Inheritance - Overriding, section Overriding Properties
You can override an inherited instance or type property to provide your own custom getter and setter for that property, or to add property observers to enable the overriding property to observe when the underlying property value changes.
You can provide a custom getter (and setter, if appropriate) to override any inherited property, regardless of whether the inherited property is implemented as a stored or computed property at source. The stored or computed nature of an inherited property is not known by a subclass—it only knows that the inherited property has a certain name and type. You must always state both the name and the type of the property you are overriding, to enable the compiler to check that your override matches a superclass property with the same name and type.
You can present an inherited read-only property as a read-write property by providing both a getter and a setter in your subclass property override. You cannot, however, present an inherited read-write property as a read-only property.
And a Note: under
If you provide a setter as part of a property override, you must also provide a getter for that override. If you don’t want to modify the inherited property’s value within the overriding getter, you can simply pass through the inherited value by returning super.someProperty from the getter, where someProperty is the name of the property you are overriding.
which tells us exactly what to do:
public class MyClass: MyBaseClass {
public override var abc: Int {
get {
return super.abc
}
set {
super.abc = newValue
}
}
}
Note that the following would also work. We just have to make sure we have a computed property:
public class MyClass: MyBaseClass {
public override var abc: Int {
didSet {
}
}
}
This looks better
public class MyClass: MyBaseClass {
override public var abc: Int {
get {
return super.abc
}
set {
super.abc = newValue
}
}
}
Some claims that this is a bug of the compiler, it doesn't synthesize correctly overridden properties.
Try the following:
public class MyClass: MyBaseClass {
private var abc: Int = 0
}
public class MyClass: MyBaseClass {
override init() {
super.init()
self.abc = 0
}
}
I'm creating MVVM application and in Model section I have simple base abstract class Animal and class Dog which derives from it:
public abstract class Animal
{
public int Age { get; set; }
}
public class Dog : Animal
{
public string Name { get; set; }
}
ViewModel section containts UI-friendly VM classes of them:
public abstract class AnimalVM<T> : ViewModelBase where T : Animal
{
protected readonly T animal;
public int Age
{
get { return animal.Age; }
set
{
animal.Age = value;
OnPropertyChanged("Age");
}
}
protected AnimalVM(T animal)
{
this.animal = animal;
}
}
public class DogVM : AnimalVM<Dog>
{
public string Name
{
get { return animal.Name; }
set
{
animal.Name = value;
OnPropertyChanged("Name");
}
}
public DogVM(Dog dog) : base(dog) { }
}
Suppose I have another VM class which contains ObservableCollection<AnimalVM>. The problem is how to create that kind of property which allow me to store there different types of Animal? I want to achieve something like this:
public class AnimalListVM : ViewModelBase
{
// here is a problem, because AnimalVM<Animal> isn't compatible with DogVM
readonly ObservableCollection<AnimalVM<Animal>> animals;
public ObservableCollection<AnimalVM<Animal>> Animals
{
get { return animals; }
}
public AnimalListVM(IList<Animal> animals)
{
//this.animals = ...
}
}
I can change ObservableCollection<AnimalVM<Animal>> property to ICollection property and then create list of AnimalVM using some dictionary Animal -> AnimalVM wrapper and Activator.CreateInstance() - it works but when I try to extend AnimalListVM adding another property SelectedAnimal which will be binded in sample View to e.g. DataGrid control I have another problem with type of that kind of property SelectedItem. It can't be of type AnimalVM<Animal> because when I have DogVM object in my Collection it won't fit with this and throw an exception.
Everything will be clear if only I had non-generic AnimalVM but I don't want to copy and paste similar properties in every DogVM, CatVM, BirdVM class derived from AnimalVM. How can I achieve this?
Ok, I've found a solution and of course it's very simple: just create another, non-generic abstract base class for your generic abstract base class and then derive your generic class from that newly created non-generic class. In that case you also must rewrite properties from non-generic class to generic class (to be more specific override them), but you do this only once, so you don't have to copy and paste the same code in every generic derived ViewModel (in our example in every DogVM, CatVM, BirdVM, etc.).